The following function intends to check whether the pointer b
is pointing to the array a[0],...,a[len-1]
?
bool between(int *a, int len, int *b)
{
return (a <= b) && (b < a + len);
}
From reading https://en.cppreference.com/w/c/language/operator_comparison the function invokes undefined behaviour. If so, what is the right way to do this? Why does the standard disallow this?
Comparing two unrelated pointers (i.e. pointers that don't point to members of the same array object or struct) using the comparison operators <
, <=
, >
, and >=
do indeed invoke undefined behavior as described in the linked page as well as section 6.5.8 of the C standard.
As to why this is disallowed, not all implementations have a flat memory model, and unrelated objects need not reside in areas of memory where performing a comparison makes sense.
So your function would return true in cases where b
points to a member of a
, false when it points one past the last member of a
, and would invoke undefined behavior otherwise.
It is however allowed to compare unrelated pointers using ==
or !=
. So you can circumvent the limitation on comparison operators by looping through the array and using equality operators to compare the target pointer with each element:
bool between(int *a, int len, int *b)
{
int i;
for (i=0; i<len; i++) {
if (a+i == b) {
return true;
}
}
return false;
}
While this is not a efficient as a ranged check, it is the only compliant way to do so.
Of course, it would be better to construct your program in such a way that such a comparison is not necessary. A program that is allowing a pointer to inside an array to fall outside of the array is already invoking undefined behavior, so fixing that would eliminate the need for such a function.
Note however that it is allowed to increment a pointer to one element past the end of an array and perform comparisons on that pointer (although it cannot be dereferenced).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With