K
Keith Thompson
There are two ways to think about pointers. It's true that (s-1) isn't
a "valid" pointer to char, because we don't (necessarily) own the
memory before s.
It's not a valid pointer because it's outside the object, whether we
"own" the memory or not. The behavior of performing the subtraction
is not defined by the standard. (Behaving as you expect is one
possible consequence of undefined behavior -- arguably the worst,
because it makes it difficult to detect bugs.)
However, if you think about a pointer as just an address in memory,
then s-1 makes sense - it's just the location in memory before s.
But C (which is what we discuss here) doesn't define pointers as just
addresses in memory, and not all machines have the same addressing
structure. Most current machines have a simple linear address space,
and allocate objects within that space, but the C standard is
specifically designed to allow for conforming implementations on
hardware with other schemes.
Segmented architectures are not uncommon. In the extreme, an
implementation could even use a distinct segment for each individual
declared object, and cause a hardware trap if you try to compute an
address outside the object where you started.
See section 4 of the comp.lang.c FAQ said:I think you are mistaken - I've definitely read that char *p=NULL; and
char *p=0; are completely equivalent.
Yes, they are, but no, I'm not mistaken. Both NULL and 0 are null
pointer constants. (Quibble: NULL is a macro that expands to an
implementation-defined null pointer constant.) When a null pointer
constant is used in a pointer context, it's implicitly converted to a
null pointer, which *may or may not* be represented as all-bits-zero.
For example, if a null pointer is represented as 0xFFFFFFFF, then the
declaration
char *p = 0;
will set p's representation to 0xFFFFFFFF.
See section 5 of the comp.lang.c FAQ.