On Mon, 2010-10-04 at 12:06 -0400, Julian Foad wrote: > The issue at hand is when NULL is defined as an unadorned '0' *and* is > passed to a variadic function such as apr_pstrcat. If that's not a > practical concern, that must be because the size and representation of > (int)0 is the same as (char *)0. If that is true on all supported > platforms, then omitting the casts is a valid option; otherwise, we need > them.
I don't think you have it quite right. If NULL is defined as, say, (void *)0, then the compiler might not warn, but it's still not correct C to pass a void * to a variadic function and then read it out as some other pointer type. void * is only guaranteed to work if it's cast (implicitly or implicitly) to the correct pointer type. We don't see this problem as run-time errors because there is typically no runtime transformation between void * and other pointer types. If NULL is defined as 0, it would be easy to imagine a practical problem where you pass a 32-bit 0 value to a variadic function and then read it back out as a 64-bit pointer type. We don't see this problem in practice because NULL is typically defined as 0L rather than just 0, and sizeof(long) typically matches the size of pointers. In terms of code hygiene, passing an uncasted NULL to a variadic function isn't any worse than using calloc() to initialize pointer fields in structures. But if your compiler is giving you grief about it, the best thing to do is probably to get used to casting in that situation. Phillip wrote: > In C++ the cast should be more common since a conforming NULL cannot > have a cast but, in the free software world at least, GCC uses > compiler magic to make plain NULL work as a pointer without a cast. Unlike C, C++ doesn't allow implicit casts from void * to other pointer types, so defining NULL as (void *)0 would be pretty inconvenient there.