Favorite FAQ entry from the “comp.lang.c FAQ” for today:
C programmers traditionally like to know a lot (perhaps more than they need to) about the underlying machine implementation. The fact that null pointers are represented both in source code, and internally to most machines, as zero invites unwarranted assumptions. The use of a preprocessor macro (NULL) may seem to suggest that the value could change some day, or on some weird machine. The construct “if(p == 0)” is easily misread as calling for conversion of p to an integral type, rather than 0 to a pointer type, before the comparison. Finally, the distinction between the several uses of the term “null” (listed in question 5.13) is often overlooked.
One good way to wade out of the confusion is to imagine that C used a keyword (perhaps nil, like Pascal) as a null pointer constant. The compiler could either turn nil into the appropriate type of null pointer when it could unambiguously determine that type from the source code, or complain when it could not. Now in fact, in C the keyword for a null pointer constant is not nil but 0, which works almost as well, except that an uncast 0 in a non-pointer context generates an integer zero instead of an error message, and if that uncast 0 was supposed to be a null pointer constant, the resulting program may not work.
I just fixed another bug which was caused by dereferencing a null pointer :-/