Hi,
I read that pointer representation can non-zero bit pattern, machine
specific.Compiler when comes accross value '0' in pointer context,
converts it to machine specific null pointer bit-pattern.
My question is if a program refers to that specific value which is
used by the machine to refer to null pointer, how compiler treats
that?.
Lets say on my machine a null pointer of type char* has the same
representation in memory as an unsigned long with a value of
0xdeadbeef. Lets also assume that sizeof (char *) = sizeof (unsigned
long) = sizeof (float).
unsigned long zero = 0;
unsigned long deadbeef = 0xdeadbeef;
char* p;
float f;
memcpy (&p, &zero, sizeof (p)); // p is now garbage
memcpy (&p, &deadbeef, sizeof (p)); // p is now a null pointer.
p = NULL; // p is now a null pointer
p = 0; // p is now a null pointer
p = 0xdeadbeef; // Doesn't compile
p = zero; // Doesn't compile
p = deadbeef; // Doesn't compile
p = (char *) 0xdeadbeef; // Implementation defined, could be null
pointer or garbage
p = (char *) 0; // In C99 it is guaranteed to be a null pointer
p = (char *) zero; // In C99 it is guaranteed to be a null pointer
p = (char *) deadbeef; // Implementation defined, could be null
pointer or garbage.
f = 0; // f has a value of 0
f = 0xdeadbeef; // f has a value quite close to 0xdeadbeef, but likely
not exactly the same
f = zero; // f has a value of 0
f = deadbeef; // f has a value quite close to 0xdeadbeef
memcpy (&f, &zero, sizeof (f)); // f could have any value, but in many
implementations it is zero.
memcpy (&f, &deadbeef, sizeof (f)); // f could have any value, most
lkely very different from 0xdeadbeef.
Remember: Pointers are not numbers. Pointers and numbers are very
different things. A "null pointer" is completely different from a
number zero, it is a pointer pointing to nothing, a number zero is a
number. Numbers have a representation (that is the bit pattern that
can be found in memory), and so have pointers; these representations
are completely unrelated. Just like float and unsigned long having
very different representations, so have char* and unsigned long. The
compiler identifies the particular construction called "null pointer
constant" and replaces it with a null pointer in certain situations
(but not in others). C99 also included the rule that an integer with a
value of zero, when cast to a pointer, always produces a null pointer.
Casting from integer to pointer can change the representation, just as
casting from integer to float can change the representation.
Cases where a null pointer constant is not replaced with a null
pointer:
int i = 0; // Thank heavens 0 is not a null pointer here.
char *p = "x"; int i = (p >= 0); // Doesn't compile.
These are not null pointer constants, but are null pointers:
(char *) 0
(char *) NULL
(char *) (void *) 0
(void *) (void *) 0
(void *) (void *) NULL
(void *) NULL // on some implementations, not on others.