2

So I have a function that returns a pointer to an element in an array A. I have another function that takes that pointer as a parameter. However, I need that function to be able to deal with the possibility that it may be passed a completely arbitrary pointer.

Is there a way to be able to detect if a pointer points somewhere within a structure? In this case, my array A?

I've seen similar questions regarding C++, but not with C.

2
  • There's probably another question asking this. Sorta. The standard doesn't say it will work, but if you know the array start, the number of elements and the size of each element, as well as the pointer you're given, then you can tell if the given pointer falls between the start and the end of the array. The trouble is, if the pointer is outside the range, the comparisons are not guaranteed to work by the standard, though most often these days, on non-segmented machines (most of them), it does in fact work. Commented Oct 30, 2016 at 3:31
  • If you are dealing with arrays, why not receiving offsets? I mean, a simple integer to be used as index. That way you save on checking belonging. Commented Oct 30, 2016 at 4:56

2 Answers 2

5

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

Sign up to request clarification or add additional context in comments.

6 Comments

Clever! That gets rid of the warnings
int array[100000]; … Ouch! But that's what the standard says will work.
It is also worthy to say that substracting pointers (for example ptr - A) yields also undefined behaviour unless both pointers come from the same array, or unless in C++.
@JonathanLeffler Seems like this should be an easy compiler optimization to make, although neither gcc nor clang seem to do it, even with int replaced by char
@qbolec no, the == operator for pointers is well-defined for all valid pointers
|
1

In section §6.5.8 Relational operators, the C11 standard (ISO/IEC 9899:2011) says:

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.

If you know that the pointer is within range of the array, then comparisons work. If the pointer is outside the range, you can't be sure that the comparisons will work. In practice, it usually does, but the standard explicitly says that the comparison yields undefined behaviour.

Note that for an array SomeType array[20];, the address &array[20] is guaranteed to be valid and to compare reliably with any address from &array[0] through &array[19]. You need to decide whether you want to count that as being in your array.

Subject to the observation that the standard does not guarantee that it will work, then, you can compare two int pointers:

int within_int_array(int *array, size_t num_ints, int *ptr)
{
    return ptr >= array && ptr < array + num_ints;
}

These days, you should be increasingly cautious about invoking undefined behaviour. Compilers do nasty things to programs that use undefined behaviour, and technically, you have no recourse since the standard says "undefined behaviour".

1 Comment

@DavidBowling: It (a hash table, or something like it) could be used, but I can't help but feel that it would be better to know where your pointers point than to need so much infrastructure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.