Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ is it legal to take the address of 2 or more past the end of the array?

Tags:

c++

arrays

From Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?

It seems that there is language specific to taking the address of one more than an array end.

Why would 2 or 2,000,000 past the end be an issue if it's not derefferenced?

Looking at some simple loop:

int array[];
...
for (int i = 0: i < array_max; ++i)
{
       int * x = &array[i *2];      // Is this legal
       int y=0;
       if (i * 2 < array_max)       // We check here before dereference
       {
              y = *x;               // Legal dereference
       }
       ...
}

Why or at what point does this become undefined, in practice it just sets a ptr to some value, why would it be undefined if it's not refferenced?

More specifically - what example of anything but what is expected to happen could there be?

like image 580
Glenn Teitelbaum Avatar asked Jan 01 '14 22:01

Glenn Teitelbaum


People also ask

Is it valid to address one element beyond the end of an array?

It does, however, allow a pointer to point at one element beyond the end of the array. The distinction is important. Thus, this is OK: char array[N]; char *p; char *end; for (p = array, end = array + N; p < end; ++p) do_something(p);

What does the address of an array mean?

The address of an array is the address of the first element of the array. In the above array, the first element is allocated 4 bytes. The number of the first byte is the address of the element. Similarly, the second element is also residing on the next 4 bytes.

What is* array in C++?

An array is a collection of elements of the same type placed in contiguous memory locations that can be individually referenced by using an index to a unique identifier. Five values of type int can be declared as an array without having to declare five different variables (each with its own identifier).

How to declare arrays in C++?

A typical declaration for an array in C++ is: type name [elements]; where type is a valid type (such as int , float ...), name is a valid identifier and the elements field (which is always enclosed in square brackets [] ), specifies the length of the array in terms of the number of elements. int foo [5];


2 Answers

The key issue with taking addresses beyond the end of an array are segmented architectures: you may overflow the representable range of the pointer. The existing rule already creates some level of pain as it means that the last object can't be right on the boundary of a segment. however, the ability to form this address was well established.

like image 104
Dietmar Kühl Avatar answered Sep 17 '22 23:09

Dietmar Kühl


Since array[i *2] is equivalent to *((array) + (i*2)), we should look at the rules for pointer addition. C++11 §5.7 says:

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.

So you have undefined behaviour even if you don't perform indirection on the pointer (not to mention that you do perform indirection, due to the expression equivalence I gave at the beginning).

like image 27
Joseph Mansfield Avatar answered Sep 17 '22 23:09

Joseph Mansfield