#define NULL 0
A discussion elsewhere raised the question of null pointers and varargs functions. The issue is essentially that NULL on its own is not guaranteed to a be a null pointer, and varargs functions are one of the contexts where this may actually matter. (The comp.lang.c FAQ has a whole section on this area.)
In particular a platform with 32-bit ints and 64-bit pointers that defined NULL to 0 would be expected to pass a value of the wrong size when just NULL was used where a pointer was expected by a varargs function.
I looked at a number of platforms to see how they defined NULL and what the outcome was.
Platform | Definition of NULL |
---|---|
Solaris | 0 on 32-bit, 0L on 64-bit |
AIX | 0 |
Linux | ((void *)0) |
HPUX | 0L |
Windows | ((void *)0) |
Mac OS X | ((void *)0) |
In all cases my test program (which passed a bare NULL for printf()'s %p conversion specifier) worked fine.
For the Windows/Linux/Mac definition of ((void *)0) this is completely unsurprising.
For HPUX, long is always the same width as a pointer. The same is true on Solaris but they went for distinct definitions for 32- and 64-bit anyway, probably to remain absolutely identical to historical definitions for 32-bit builds.
AIX is the slightly surprising one. Superficially in a 64-bit build you're passing a 32-bit value where a 64-bit value is required. In practice it turns out that it always gets away with it: the code generated to store even a 32-bit 0 is:
addi r30,r0,0 std r30,184(SP)
i.e. it always stores a 64-bit 0 even if you only ask for 32 bits (std is “store double-word”, a word being 32 bits in this context.)
no subject
printf("%d %p %d", 1, NULL, 2)
, does it still get it right?no subject
no subject
(Personally, I'm using xlC on AIX, last 64-bit compile being 30 minutes ago, next being (I hope) months away.)
no subject
no subject
no subject
It always passes 64 bits, even if it doesn't know anything about the called function. Source code:
(Lots of args because if you only have a few they end up in registers instead of on the stack.)
Assembler fragment:
If you turn on optimization then the assembler is harder to read as things are re-ordered rather, but it's still all std.