I quote from "The C Programming Language" by Kernighan & Ritchie:
Any pointer can be meaningfully compared for equality or inequality with zero. But the behavior is undefined for arithmetic or comparisons with pointers that do not point to members of the same array. (There is one exception: the address of the first element past the end of an array can be used in pointer arithmetic.)
Does this mean I cannot rely on ==
for checking equality of different pointers? What are the situations in which this comparison leads to a wrong result?
The equality operator is defined for all valid pointers, and the only time it can give a "false positive" is when one pointer points to one element past the end of an array, and the other happens to point (or points by virtue of a structure definition) to another object stored just past the array in memory.
I think your mistake is treating K&R as normative. See the C99 standard (nice html version here: http://port70.net/~nsz/c/c99/n1256.html), 6.5.9 on the equality operator. The issue about comparisons being undefined only applies to relational operators (see 6.5.8):
I interpret this as following:
Here it is valid to say that
because
c
results froma
via pointer arithmetic,but not necessarily that
or
or something alike, because they result from different arrays, whose order and alignment in memory is not defined.
You cannot use pointer comparison for comparing pointers that point into different arrays.
So:
int arr[5] = {1, 2, 3, 4, 5};
int * p = &arr[0];
int anotherarr[] = {1, 2};
int * pf = &anotherarr[0];
You cannot do
if (p == pf)
sincep
andpf
do not point into the same array. This will lead to undefined behaviour.You can rely on pointer comparison if they point within the same array.
Not sure about the arithmetic case myself.
You can do
==
and!=
with pointers from different arrays.<, <=, >, >= is not defined.
One example that comes to my mind is Harvard architecture with separate address spaces for code and for data. In computers of that architecture the compiler can store constant data in the code memory. Since the two address spaces are separate, a pointer to an address in the code memory could be numerically equal to a pointer in the data memory, without pointing to the same address.