序言:众所周知,将指针放在数组末尾之后是合法且明确定义的:
int main()
{
int na [1] = {};
const int* naBegin = na;
const int* naEnd = na + 1; // one-past-end, OK
}
此指针可用于比较,这有助于C样式数组(或更准确地说,其中的指针)与采用迭代器的标准库例程兼容,例如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);
}
标准(C ++ 03参考)支持其合法性和定义性:
5 /当添加或减去具有整数类型的表达式时 从指针开始,结果具有指针操作数的类型。如果 指针操作数指向数组对象的元素和数组 足够大,结果指向一个偏离的元素 原始元素使得下标的差异 结果和原始数组元素等于整数表达式。 换句话说,如果表达式P指向一个的第i个元素 数组对象,表达式(P)+ N(等效地,N +(P))和(P)-N (其中N具有值n)分别指向第i + n和第i 数组对象的第i个元素,只要它们存在即可。而且,如果 表达式P指向数组对象的最后一个元素, 表达式(P)+1指向数组对象的最后一个元素, 如果表达式Q指向一个数组的最后一个元素 对象,表达式(Q)-1指向数组的最后一个元素 object。如果指针操作数和结果都指向元素 相同的数组对象,或一个超过数组的最后一个元素 对象,评估不得产生溢出;否则, 行为未定义。
当我在标准中查看对过去指针的浊度的引用时,我发现的每个引用都在讨论数组。如果我们试图将对象的地址过去,而不是数组呢?
问题:是否可以将单个对象视为未分配为数组,就像它是一个数组并采取有效的一个 - 过去 - 所述对象的结束地址?
例如(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);
}
此代码是否合法且标准定义明确?
答案 0 :(得分:10)
答案在您引用的段落之前的段落中:
4 /为了这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型。
(注意:我引用的是C ++ 11,因为我手头没有C ++ 03.我很确定没有任何改变。)
所以是的,&na + 1
是一个有效的过去指针。