Checking If Pointer Points Within an Array

Check if a pointer points inside an array in standard C/C++

It depends on what you mean by UB.

Specifically, for pointer comparisons, section 5.9 "Relational Operators" of the C++ standard says:

If two pointers p and q of the same type point to different objects that are
not members of the same object or to different functions or if only one of
them is null, the results of p<q, p>q, p<=q and p>=q are unspecified.

Note that the behaviour is unspecified (meaning that the result of the comparison could be true or false - in other words the result doesn't tell you anything useful - but the implementation isn't required to specify which) as opposed to undefined (meaning that the compiler or the resulting program could do anything at all).

However, so far I have only seen one family of implementations that didn't do the expected thing with code like Kirill's:

bool inside = (other_pointer >= array) && (other_pointer < array+size);

Those implementations are compilers intended for building MS-DOS real-mode programs, in which addresses have a paragraph and offset part. The addresses FF00:0010 and FF01:0000 point to the same memory location but if I recall correctly the compilers weren't guaranteed to behave in the expected way, except when compiling for some memory models (certainly the HUGE model but perhaps others).

However, if either p or q does not point to an existing object (because for example the pointer was freed) then the behaviour is going to be undefined no matter what you do. So you can't use this kind of method to figure out if a pointer is still valid.

Check if pointer points to given array

The only portable way is to use an equality test against all of the possible valid values for the pointer. For example:

int A[10];

bool points_to_A(int *ptr)
{
for (int i = 0; i < 10; ++i)
if ( ptr == &A[i] )
return true;

return false;
}

Note that using a relational operator (e.g. <), or subtraction, with two pointers is undefined behaviour unless the two pointers actually do point to elements of the same array (or one past the end).

How to test if pointer inside an array?

How to test if pointer inside an array?

Code can use >=, >, <, <= between two object pointers p,q is they are in the same array (or just one passed the end of the array). Else code is undefined behavior. C does not have a portable way to test in/outside the array.

The below code is poor

if (myCurrentPtr == (a + _B)) {                            // Defined behavior
printf("pointer just passed a[]\n");
} else if (myCurrentPtr >= a && myCurrentPtr < (a + _B)) { // Undefined behavior
printf("pointer in array\n");
} else {
printf("pointer outside array\n");
}

Code could explicitly compare one at a time with ==, != with myCurrentPtr and each element of a[]. Likely this is unsatisfactorily slow, yet reliable.

// Dependable, well defined, but slow.
found = false;
for (int i=0; i<5; i++) {
if (myCurrentPtr == &a[i]) {
found = true;
break;
}
}

Other approaches rely on iffy code.

// Iffy code - depending on memory model, may work, may not.
uintptr_t mcp = (uintptr_t) myCurrentPtr;
uintptr_t ia = (uintptr_t) a;
uintptr_t ia5 = (uintptr_t) &a[5];

if (mcp >= ia && mcp < ia5) { // Not highly portable
printf("pointer in array\n");
} else {
printf("pointer just passed a[]\n");
}

The best approach to "How to test if pointer inside an array?" is to re-form the problem. OP did not post why this test is needed. Good code typically can re-work the issue and not use this test.

checking if pointer points within an array

Although the comparison is valid only for pointers within the array and "one past the end", it is valid to use a set or map with a pointer as the key, which uses std::less<T*>

There was a big discussion on this way back in 1996 on comp.std.c++

How to check if a pointer points to an array or single int or char

Like others have said here, C doesn't know what a pointer is pointing to. However if you should choose to go down this path, you could put a sentinel value in the integer or first position in the array to indicate what it is...

#define ARRAY_SENTINEL -1

int x = 0;
int x_array[3] = {ARRAY_SENTINEL, 7, 11};

pointer = &x_array[0];

if (*pointer == ARRAY_SENTINEL)
{
// do some crazy stuff
}

pointer = &x;

if (*pointer != ARRAY_SENTINEL)
{
// do some more crazy stuff
}

How to determine if a pointer equals an element of an array?

If you want to comply with the C Standard then your options are:

  • Perform individual == or != tests against each pointer in the target range

    • You could use a hash table or search tree or something to speed this up, if it is a very large set
  • Redesign your code to not require this check.

A "probably works" method would be to cast all of the values to uintptr_t and then do relational comparison. If the system has a memory model with absolute ordering then it should define uintptr_t and preserve that ordering; and if it doesn't have such a model then the relational compare idea never would have worked anyway.

How to check whether a pointer is pointing to an element inside an array?

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).

Any way to detect whether the pointer points to array?

No, unfortunately not. C++ RTTI does not extend to primitive types.

Check if a pointer points to a valid structure

You can only check if pointer is valid by doing pointer != NULL because anything except `NULL' is treated by valid pointer.

In your case, to check if your pointer points to any of your array entry, you can only do this:

size_t i = 0;
int isValid = 0;
for (i = 0; i < N; i++) {
if (test_ptr == &array[i]) {
isValid = 1;
break;
}
}

if (isValid) {
//Pointer points to one of your array entry
}

But in general, you cannot just test if pointer points to specific valid location for you. It is up to you to take care of where it points. It can also have NON-NULL value but points to invalid location, for example:

int* ptr = malloc(10); //Now points to allocated memory
*ptr = 10;
free(ptr); //Free memory
*ptr = 10; //Undefined behaviour, it still points to the same address but
//we don't know what will happen. Depends on implementation


Related Topics



Leave a reply



Submit