On Tue, 2005-12-06 at 16:07 -0500, Chris Shoemaker wrote: > Yes, this *works*! IFF NULL expands to "0". But, it's not portable > because NULL *may* expand to (void*)0. This is *exactly* why using > "NULL" (or even "0") as a sentinel is not portable. Portable code > *must* explicitly cast sentinels. Don't blame me - blame Ritchie. > > Remember: arguments to variadic functions are NOT in a pointer > context.
After reading what Stuart D. Gathman wrote in this thread, I'm thinking that it's not Ritchie's fault either. It's a matter of mapping the C language to the hardware and it's assembly language. I was going to respond that I think it's BS to have to cast the NULL pointer, but now I see why it is necessary. It does have to do with context. If it's a pointer to a type where the pointer is 8 bits, and the stdarg code expects a (void *)0 that turns out to be 32 bits... the input argument is not automatically extended to 32 bits because the compiler cannot see the need for it unless you tell it with the cast or an assignment to a variable with a larger sized pointer type. We probably should not even assume that (equalp NULL 0). Maybe it's 0xff? In either case, the explicit cast to (void *) will port, right? Q: Why can't the stdarg.h code perform that typecast internally so that client code does not have to? And... from info libc, on variadic functions: 8<------------------------------------------------------------------------>8 Since the prototype doesn't specify types for optional arguments, in a call to a variadic function the default argument promotions are performed on the optional argument values. This means the objects of type char or short int (whether signed or not) are promoted to either int or unsigned int, as appropriate; and that objects of type float are promoted to type double. So, if the caller passes a char as an optional argument, it is promoted to an int, and the function can access it with va_arg (ap, int). Conversion of the required arguments is controlled by the function prototype in the usual way: the argument expression is converted to the declared argument type as if it were being assigned to a variable of that type. 8<------------------------------------------------------------------------>8 It says that this "default argument promotions" feature is required by ISO C. So shouldn't a small pointer type be promoted automatically to a larger pointer type, by the compiler? (Of course it cannot happen at run-time in C.) What settles it once and for all is this, from info libc, "The NULL Pointer Constant": 8<------------------------------------------------------------------------>8 If you use the null pointer constant as a function argument, then for complete portability you should make sure that the function has a prototype declaration. Otherwise, if the target machine has two different pointer representations, the compiler won't know which representation to use for that argument. You can avoid the problem by explicitly casting the constant to the proper pointer type, but we recommend instead adding a prototype for the function you are calling. 8<------------------------------------------------------------------------>8 -- Karl Hegbloom <[EMAIL PROTECTED]> _______________________________________________ gnucash-devel mailing list gnucash-devel@gnucash.org https://lists.gnucash.org/mailman/listinfo/gnucash-devel