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?)
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).
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".
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.
Function pointers are signed with a key that's fixed across all processes, allowing sharing of library code between processes.
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.
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.
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