Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are comparisons on out-of-range pointers well-defined?

Given the following code:

char buffer[1024];
char * const begin = buffer;
char * const end = buffer + 1024;
char *p = begin + 2000;
if (p < begin || p > end)
    std::cout << "pointer is out of range\n";

Are the comparisons performed (p < begin and p > end) well-defined? Or does this code have undefined behaviour because the pointer has been advanced past the end of the array?

If the comparisons are well defined, what is that definition?

(extra credit: is the evaluation of begin + 2000 itself undefined behaviour?)

like image 507
John Bartholomew Avatar asked Dec 21 '12 21:12

John Bartholomew


People also ask

How to get value out of pointer?

To get the value pointed to by a pointer, you need to use the dereferencing operator * (e.g., if pNumber is a int pointer, *pNumber returns the value pointed to by pNumber . It is called dereferencing or indirection).

How pointers work in a c++ program to reference and dereference data?

Pointers are said to "point to" the variable whose address they store. An interesting property of pointers is that they can be used to access the variable they point to directly. This is done by preceding the pointer name with the dereference operator ( * ). The operator itself can be read as "value pointed to by".

How to define a pointer c++?

Create a pointer variable with the name ptr , that points to a string variable, by using the asterisk sign * ( string* ptr ). Note that the type of the pointer has to match the type of the variable you're working with.

Are pointers signed?

Function pointers are signed with a key that's fixed across all processes, allowing sharing of library code between processes.


2 Answers

I'll assume the C++11 standard. According to section 5.7 (Additive Operands) paragraph 5, the behavior of *p = begin + 2000 is undefined first, before you even get to the comparison:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

like image 149
Dmitry B. Avatar answered Oct 26 '22 07:10

Dmitry B.


The evaluation of begin+2000 is undefined, it's going past the end of the array - you can go up to one past the end, but not further.

From C++11 §5.7/5 Additive operators:

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

For pointer comparisons to be specified, assuming you have valid pointers to start with, they essentially need to be pointers to the same array (or one past the end), or pointers to non-static data members of the same access control of the same object (unless it's an union...).

The details are in §5.9/2 Relational operators:

Pointers to objects or functions of the same type (after pointer conversions) can be compared, with a result defined as follows:

  • If two pointers p and q of the same type point to the same object or function, or both point one past the end of the same array, or are both null, then p<=q and p>=q both yield true and p<q and p>q both yield false.
  • If two pointers p and q of the same type point to different objects that are not members of the same object or elements of the same array 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.
  • If two pointers point to non-static data members of the same object, or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control (Clause 11) and provided their class is not a union.
  • If two pointers point to non-static data members of the same object with different access control (Clause 11) the result is unspecified. — If two pointers point to non-static data members of the same union object, they compare equal (after conversion to void*, if necessary). If two pointers point to elements of the same array or one beyond the end of the array, the pointer to the object with the higher subscript compares higher.
  • Other pointer comparisons are unspecified.
like image 6
3 revs, 2 users 96% Avatar answered Oct 26 '22 05:10

3 revs, 2 users 96%