Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
192 views
in Technique[技术] by (71.8m points)

c++ - 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, "
"));
}
int main()
{
  int na = 42;
  foo <int> (&na, &na + 1);
}

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...