Constraints on Pointer Arithmetic Past an Array’s End

In Standard C and C++, the address of the first element past the end of an array can be used in pointer arithmetic. Thus, you can initialize a vector with the contents of a built-in array, like this:

   int arr[3] = {1, 2, 3};  vector  vi ( arr,          //address of  the array's beginning                             arr + 3 );  // address of one element past the array's end

Now consider an almost identical version of this example:

   vector  vi ( &arr[0],     //address of  the array's beginning                             &arr[3] );   // address of one element past the array's end

Both forms seem to be correct and identical but they are not. While the Standard allows you to take the address of one element past the array’s end (as shown in the first example), the second example does something different. To understand the difference, it is important to know how precisely the expression &arr[3] is interpreted. First, the subexpression arr[3] is evaluated to *(arr+3), that is, the element located one position past the array’s end is read. However, no such element exists. Next, the address of the non-existent element is taken. In other words, &arr[3] is equivalent to &(*(arr+3)), which is very different from arr+3. The first example is legal, while the other is undefined (although in practice, it will work on most compilers as expected).

Most experienced C and C++ programmers are surprised that &arr[3] isn’t completely equivalent to arr+3. In fact, it even surprised the C committee, who heard about the issue only recently. Hopefully, this loophole will be fixed in the upcoming revision of the C standard.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: