Seebs said:
No. It doesn't even promise you that there is a meaningful comparison
between the addresses of different automatic variables. Comparisons are
meaningful only within an object (and also addresses within an object can
be compared to the address "one past the end" of that object).
There is one additional condition, but it's not terribly useful, and it
applies only to equality operators.
N1256 6.5.9p6-7:
6 Two pointers compare equal if and only if both are null pointers,
both are pointers to the same object (including a pointer to an
object and a subobject at its beginning) or function, both are
pointers to one past the last element of the same array object,
or one is a pointer to one past the end of one array object and
the other is a pointer to the start of a different array object
that happens to immediately follow the first array object in
the address space.
7 For the purposes of these operators, a pointer to an object that
is not an element of an array behaves the same as a pointer to
the first element of an array of length one with the type of
the object as its element type.
(Paragraph 7 doesn't appear in the C99 standard; it's more of a
clarification than new semantics. Both C99 and N1256 have similar
wording for relational operators (<, <=, >, >=)).
There's a footnote attached to the end of paragraph 6:
Two objects may be adjacent in memory because they are adjacent
elements of a larger array or adjacent members of a structure
with no padding between them, or because the implementation
chose to place them so, even though they are unrelated. If prior
invalid pointer operations (such as accesses outside array
bounds) produced undefined behavior, subsequent comparisons
also produce undefined behavior
The purpose of the "happens to immediately follow" isn't to permit
code to depend on distinct objects being adjacent; it applies
only if they *happen* to be adjacent, but there's no way to cause
them to be adjacent unless they're elements of the same array
(even struct members can have padding between them). The point
is that implementations aren't required to go out of their way to
cause two pointers to appear to be unequal if they happen to point
to the same location in memory.
For example, the following program could produce any of three possible
outputs:
#include <stdio.h>
int main(void)
{
int x;
int y;
if (&y == &x + 1) {
puts("&y == &x + 1");
}
else if (&x == &y + 1) {
puts("&x == &y + 1");
}
else {
puts("x and y are not adjacent");
}
return 0;
}