Introduction: This question is part of my collection of C and C++ (and C/C++ common subset) questions regarding the cases where pointers object with strictly ide
No. We cannot even infer that either branch of this code works given any particular result of memcmp()
. The object representations that you compare with memcmp()
might be different even if the pointers would be equivalent, and the pointers might be different even if the object representations match. (I’ve changed my mind about this since I originally posted.)
You try to compare an address one-past-the-end of an array with the address of an object outside the array. The Standard (§6.5.8.5 of draft n1548, emphasis added) has this to say:
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.
It repeats this warning that the result of comparing the pointers is undefined, in appendix J.
Also undefined behavior:
An object which has been modified is accessed through a restrict qualified pointer to a const-qualified type, or through a restrict-qualified pointer and another pointer that are not both based on the same object
However, none of the pointers in your program are restrict-qualified. Neither do you do illegal pointer arithmetic.
You try to get around this undefined behavior by using memcmp()
instead. The relevant part of the specification (§7.23.4.1) says:
The
memcmp
function compares the firstn
characters of the object pointed to bys1
to the firstn
characters of the object pointed to bys2
.
So, memcmp()
compares the bits of the object representations. Already, the bits of pa1
and pb
will be the same on some implementations, but not others.
§6.2.6.1 of the Standard makes the following guarantee:
Two values (other than NaNs) with the same object representation compare equal, but values that compare equal may have different object representations.
What does it mean for pointer values to compare equal? §6.5.9.6 tells us:
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.
That last clause, I think, is the clincher. Not only can two pointers that compare equal have different object representations, but two pointers with the same object representation might not be equivalent if one of them is a one-past-the-end pointer like &a[0]+1
and another is a pointer to an object outside the array, like &b
. Which is exactly the case here.