[Swan-dev] pointer initialization and fcfcde7422a4805a56a3a4a175271c56fbbbab12

D. Hugh Redelmeier hugh at mimosa.com
Mon Jul 4 19:15:17 UTC 2016


| From: Lennart Sorensen <lsorense at csclub.uwaterloo.ca>
| 
| On Sat, Jun 25, 2016 at 10:24:15PM -0400, D. Hugh Redelmeier wrote:
| > This commit is technically wrong.  I admit that the problem will not show 
| > up on most machines.
| > 
| > The C standard does not require that the binary representation of a NULL 
| > pointer be 0.  Initializing a struct by zeroing bytes does not guarantee 
| > that pointer fields are initialized to NULL.
| 
| C11 does require that in fact.
| 
| It states (in section 6.3.2.3.3):
| 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.
| 
| And I have never heard of an implementation that didn't do that.
| Doing otherwise made things like "if (!pointer) ..." too damn hard to
| get right.

Let me be clearer.  A pointer value that is null must test equal to
zero.  Not true of the raw bytes of a null pointer (no conversion
happens when you deal with the raw bytes of a pointer).

void *p;
...
	passert(NULL = 0);	/* must not fail */
...
	memset(&p, 0, sizeof(p));
	passert(p == 0);	/* may fail */
...
	p = 0;
	passert(p == 0);	/* must not fail */
...
	static const unsigned char zeros[sizeof(void *)];
	p = 0;
	passert(memcmp(&p, zeros, sizeof(void*)) == 0); /* may fail */

Some machines with segmented memory take advantage of this liberty.
But most of those have died out.


More information about the Swan-dev mailing list