As Drew McGowen pointed out in a comment, but I'll post the quote here:
6.5.8 Relational operators
5 When two pointers are compared, the result depends on the relative locations in the address space of the
objects pointed to. If two pointers to object types both point to
the same object, or both point one past the last element of the same
array object, they compare equal. If the objects pointed to are
members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared
earlier in the structure, and pointers to array elements with larger
subscript values compare greater than pointers to elements of the same
array with lower subscript values. All pointers to members of the
same union object compare equal. If the expression P points to an
element of an array object and the expression Q points to the last
element of the same array object, the pointer expression Q+1 compares
greater than P. In all other cases, the behavior is undefined.
That's from the C11
standard. C99
is the same.
From C++11
, it's more or less the same. Some tweaks about pointer conversions, I can paste it all if you want. More importantly, the behaviour is Unspecified (as Chris pointed out above).
Note that Undefined Behaviour is lethal. If you compare two unrelated pointers, your machine may catch fire, launch nuclear missiles, make demons fly out of your nose, etc.
Unspecified Behaviour has to do something vaguely reasonable. The compiler doesn't have to document it, or even do the same thing for two different programs, but it can't blow up the world. Your program is still considered valid.
So in your particular case, compiling as C
, the user could cause Undefined Behaviour depending on what they pass to the function. This seems pretty dangerous.
Also, contrary to my comment on the question, you cannot just use !=
on two arbitrary void*
s:
C11
6.5.9 Equality operators
2 One of the following shall hold:
— both operands have arithmetic type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer to an object type and the other is a pointer to a
qualified or unqualified version of void; or
— one operand is a pointer and the other is a null pointer constant.