Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange wording in the standard, concerning comparison of pointers

§6.5.8\6 (concerning >, <, <=, >=)

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.

Several sections above, §6.5.8, it is explained that basically, pointer arithmetic work as expected on arrays. That is int a[3]; int *p = a; int *q = &a[2]; //q-p == 3 is valid. However, as I read the above q > p is UB.

What am I missing?

like image 545
Vorac Avatar asked Nov 13 '22 05:11

Vorac


1 Answers

Firstly, you have quoted part of a paragraph, the first part explains what this is referencing, I include the paragraph here:

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.

Basically, the bit you were referencing refers to the fact that normally a pointer must always point either to a stand alone object, to an element of an array of objects or one past the end of an array of objects. As you can see, normally incrementing a pointer which already points to the last element of an array would yield an invalid pointer, and indeed this pointer in the standard must never be dereferenced, however it can be used for one special case which is that it can be set or compared to another pointer.

This is useful in a program in which you increment a pointer then check if it is past the end of the array and terminate if it does. For example.

int foo = 0;
int ArrSize = 6;
int bar[ArrSize];
while(foo < ArrSize)
{
    foo++;
    printf("%d", bar + 3 < bar + foo);
}

Will be legal, even in the last case where foo points one beyond the end of the array.

Note this example is very contrived but demonstrates the point.

If not for this rule this program would be undefined behaviour.

like image 154
Vality Avatar answered Nov 14 '22 23:11

Vality