Introduction
Announcements

Schedule
Labs
Assignments
TA office hours

Tests, exam

Topic videos
Some course notes
Extra problems
Lecture recordings

Discussion board

Grades so far

Why does execl()'s last argument (NULL) have to be cast?

I've been telling you to avoid unnecessary casts. When you make a function call, there is an implicit conversion to the type of the argument. A cast to that type is unnecessary, and furthermore, sometimes suppresses useful error messages saying that that conversion is impossible (e.g. casting an integer variable's value to a pointer type).

So why am I telling you to cast the NULL last argument to execl to type pointer-to-char?
Because it is necessary!
Why is it necessary?

Normally we only call a function (whether our own function or a library function or system call) in the presence of a declaration which tells the compiler all of its argument types. The compiler can then perform the necessary checking AND insert the necessary conversions.

However, these declarations are unable to describe the argument types for functions with variable numbers of arguments. Consider that you can call

execl("/bin/cat", "cat", "file1", "file2", (char *)NULL)
so, for example, the fourth argument's type is pointer-to-char; but consider that you can also call
execl("/bin/ls", "ls", (char *)NULL)
in which the fourth argument is non-existent, and the C compiler should not be enforcing that the fourth argument's type is pointer-to-char (or anything).

There is a special syntax for declaring these "variable arguments" functions which we won't go into right now. But you can see that it's not going to be able to give us the full coverage of a normal declaration. It can say that the first two arguments to execl() are of type pointer-to-char, but after that you're on your own.

NULL is defined in stdio.h as simply "0" (without quotes). Normally this gets implicitly converted to a pointer type, and we have the bizarre rule in C that a constant zero converted to a pointer type becomes the null pointer of that type.

But in execl(), we're not going to get this implicit conversion. So, unusually in modern C, we need to put in an explicit cast.

What happens if you don't?

Unfortunately, if you don't put in the cast, your program will usually work.

Why do I call this unfortunate? Because it's not the case that your program will ALWAYS work. And programs which work sometimes and fail other times are harder to debug.

Your program will only work in the exact circumstances that
1) a null pointer-to-char and the integer zero have the same exact bit representation, and
2) an integer is comprised of at least as many bytes as a null pointer-to-char value.

However, these two conditions are both extremely common, so a program lacking this required cast will usually still work.

And then, on some other computer some other day, it won't.

So put in the cast.