A previous blog post mentioned two properties of
NULL
that many developers find surprising: NULL
does not need to be 0 when stored in memory — the compiler is allowed to transform the value when casting between integer and pointer types, sounion { uintptr_t u; void *p; } u; u.p = NULL; printf("0x%" PRIxPTR "\n", u.u);
does not need to print 0, even thoughu.p==(void*)0
evaluates to true.NULL
does not need to be a pointer — it is valid for an implementation to defineNULL
as#define NULL 0
so it is not portable to passNULL
to ava_arg
function, as this will fail for architectures wheresizeof(int)!=sizeof(void*)
.
Today I found a third case in the paper "Beyond the PDP-11: Architectural support for a memory-safe C abstract machine" — casting an integer variable having the value 0 to a pointer type is not guaranteed to produce a null pointer. For example, it is implementation-defined if the comparison
int zero = 0; bool b = (void*)0 == (void*)zero;
evaluates to true or false. Both
(void*)0
and (void*)zero
cast the value 0 to void*
, so I had naively thought that both would produce a null pointer, but the standard does only guarantee this for (void*)0
as it is a constant expression
An integer constant expression with the value 0, or such an expression cast to type void *
, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
while the result is implementation-defined when casting a variable
An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
So
(void*)0
is a null pointer while (void*)zero
is converted in an implementation-defined manner, which may or may not produce a null pointer...
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.