Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treating a single object like an array with one element, taking one-past-end pointer

Preamble: It is well-known that taking the pointer one past the end of an array is legal and well-defined:

int main()
{
  int na [1] = {};
  const int* naBegin = na;
  const int* naEnd = na + 1; // one-past-end, OK  
}

This pointer can be used in comparisons, which contributes to C-style arrays (or, more accurately, pointers therein) being compatible with Standard Library routines which take iterators, such as copy (Live Demo):

template <typename Field, typename Iter>
void foo(Iter begin, Iter end)
{
  std::copy (begin, end, std::ostream_iterator <Field> (std::cout, std::endl);
}
int main()
{
  int na [1] = {};
  foo <int> (na, na + 1);
}

The legality and definedness of this is supported by the Standard (C++03 reference):

5.7 Additive operators

5/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. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i–n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. 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.

When I've looked in the Standard for references to the vlaidity of past-the-end pointers, every reference I've found is discussing arrays. What if we were to try to take past-the-end the address of an object, not an array?


Question: Is it possible to treat a single object, not allocated as an array, as if it were an array and take a valid one-past-the-end address of said object?

For instance (Live Demo):

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <iterator>

template <typename Field, typename Iter>
void foo(Iter begin, Iter end)
{
  std::copy (begin, end, std::ostream_iterator <Field> (std::cout, "\n"));
}
int main()
{
  int na = 42;
  foo <int> (&na, &na + 1);
}

Is this code legal and well-defined by the Standard?

like image 938
John Dibling Avatar asked Jan 28 '14 16:01

John Dibling


People also ask

Can you reference past the last element in an array?

It is legal. According to the gcc documentation for C++, &array[5] is legal. In both C++ and in C you may safely address the element one past the end of an array - you will get a valid pointer.

Can you treat a pointer as an array?

So when you have a pointer that points to a block of memory, such as an array or a part of an array, you can treat that pointer ``as if'' it were an array, using the convenient [i] notation.

What is a single item in an array called?

Each variable or object in an array is called an element.

How can I get a last element in array in php?

You can use the end() function in PHP to get the last element of any PHP array. It will set the internal pointer to the last element of the array and return its value.

When a pointer to an array is dereferenced?

Pointer to an array points to an array, so on dereferencing it, we should get the array, and the name of array denotes the base address. So whenever a pointer to an array is dereferenced, we get the base address of the array to which it points.

How to access elements in a two dimensional array using pointers?

Pointers and two dimensional Arrays: In a two dimensional array, we can access each element by using two subscripts, where first subscript represents the row number and second subscript represents the column number. The elements of 2-D array can be accessed with the help of pointer notation also.

What happens when you dereference an array in C++?

On dereferencing a pointer expression we get a value pointed to by that pointer expression. Pointer to an array points to an array, so on dereferencing it, we should get the array, and the name of array denotes the base address. So whenever a pointer to an array is dereferenced, we get the base address of the array to which it points.

How to access elements of a 2-D array in C++?

The elements of 2-D array can be accessed with the help of pointer notation also. Suppose arr is a 2-D array, we can access any element arr [i] [j] of the array using the pointer expression * (* (arr + i) + j).


1 Answers

The answer is in the paragraph before the one you quote:

4/ For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

(Note: I'm quoting C++11 as I don't have C++03 to hand. I'm fairly sure nothing has changed.)

So yes, &na + 1 is a valid past-the-end pointer.

like image 63
Mike Seymour Avatar answered Oct 02 '22 18:10

Mike Seymour