struct foo {
void * bar;
} baz;
...
memset(&baz, 0, sizeof(struct foo));
assert(baz.bar == NULL);
it's possible for the assertion to fail, since NULL it not guaranteed to be represented in memory by a zero bytes. struct foo {
void * bar;
} baz;
...
memset(&baz, 0, sizeof(struct foo));
assert(baz.bar == NULL);
it's possible for the assertion to fail, since NULL it not guaranteed to be represented in memory by a zero bytes.(You're absolutely correct that the standard does not require NULL be represented with zero bits, though.)
Technically correct (which is of course the best kind of correct) but you'd be hard pressed to find a system in 2019 where NULL != (void*)0. The most recent machines with non-zero NULL in the C FAQ entry on the matter (http://c-faq.com/null/machexamp.html) date back to the mid '90s.
This expression is false in any C99 compliant system:
Section 6.3.2.3 [0]:
> An integer constant expression with the value 0, or such an expression cast to type void * , is called a null pointer constant. [1] 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
> Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
The technicality of the memset example is that it does not set the bits of the pointer by referring to it as a pointer, so the requirement that 0 behave as if it was a null pointer does not apply.
[0] http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
[1] In text footnote: The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17
EDIT: Formatting
NULL == (void*)0.
But given void *p = 0;
intptr_t i = 0;
it is not guaranteed that `memcmp(&i, &p, sizeof(p)) == 0`.Even less intuitively, it is not guaranteed that `(void*)i == p` since `i` is not an integer constant expression, even if the value is known to be 0.
You'd be hard pressed to find a system at any time where NULL is not equal to a compile-time constant zero. ;-)
But talking about the actual bit representation. A zero value as a special pointer with the magic property of being invalid is a convention for C on x86, right?
I assume it has to do with it's fast to check the zero-flag in EFLAGS register when doing checks for null pointers.
However, what has bitten me is memsetting structures that I later turn into full-fledged classes in C++. Oops, there went the VMT.
Designated initializers are very nice, as is the ability (in C++) to provide initial-value assignments that run before the constructor.
T foo = {}The examples listed here are all historical:
If you use memset to initialize structure with pointers with 0 and then test if the pointer are NULL, the compiler could assume that the pointer was not properly initialized and remove the if completely, or actually even remove the whole function.
FWIW I'm less strict about standards compliance in the libarchive-derived code, since that frobs lots of unportable bits anyway.
struct S {size_t a, void *p;};
foo = (struct S) {0};
Does the standard require the compiler to set any pointers to NULL, or will everything be implicitly zeroed leaving pointers possibly improperly initialized to NULL?