Processing a single object, such as an array with one element, with a one-way pointer

Preamble: It is well known that accepting a pointer at 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 comparison, which contributes to C-style arrays (or rather pointers) that are compatible with standard library programs that accept 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 certainty of this is confirmed by the standard (link to C ++ 03):

5.7 Additive operators

5 / When an expression with an integral type is added or subtracted from the pointer, the result is of the operand type of the pointer. If the pointer operand points to an element of the array object, and the array is large enough, the result indicates the offset of the element from the original element such that the difference between the indices of the resulting and initial elements of the array is equal to the integral expression. In other words, if the expression P points to the ith element of the array, the expressions (P) + N (equivalently, N + (P)) and (P) -N (where N has the value n) indicate respectively the ith + nth and in-th elements of the array, if they exist. Moreover, if the expression P points to the last element of the array object, the expression (P) +1 indicates one after the last element of the array object, and if the expression Q indicates one after the last element of the array object, the expression (Q) -1 indicates the last element of the array object. If both pointer operands and the result point to elements of the same array object, or one after the last element of the array, the evaluation should not lead to overflow; otherwise, the behavior is undefined.

When I looked at the Standard for references to vlaidity pointers of the past, every link I found discusses arrays. What if we should try to use the end-to-end address of the object, rather than the array?


Question: Is it possible to process a single object, not selected as an array, as if it were an array and accept a valid one-last-end address of the specified object?

For example ( 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 a legitimate and well-defined Standard?

+6
source share
1 answer

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

4 / For the purposes of these operators, a pointer to a nonarray object behaves in the same way 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 am quoting C ++ 11 as I do not have C ++ 03. I am sure nothing has changed.)

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

+10
source

All Articles