当前位置: 首页 > 知识库问答 >
问题:

将单个对象视为具有一个元素的数组,使用一个过去的结束指针

司空通
2023-03-14

前言:众所周知,将指针1放在数组末尾是合法且定义明确的:

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和第i–N个元素,前提是它们存在。此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)1指向数组对象最后一个数组元素的后面一个元素;如果表达式Q指向数组对象最近一个元素的前面一个元素时,表达式(Q)-1指向数组对象上一个元素。如果指针操作数和结果都指向同一数组对象的元素,或者超过数组对象的最后一个元素,则求值不应产生溢出;否则,行为是未定义的。

当我在标准中查找对过末指针的vlaidity的引用时,我发现的每一个引用都在讨论数组。如果我们试图获取一个对象的地址,而不是一个数组的地址,会怎么样呢?

问:有没有可能把一个没有作为数组分配的对象当作一个数组来处理,并获取这个对象的一个有效的结束前地址?

例如(现场演示):

#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);
}

这个代码是否合法,是否由标准明确定义?

共有1个答案

柯骏
2023-03-14

答案就在你引用的那段话之前:

4/就这些操作符而言,指向非数组对象的指针的行为与指向长度为1的数组的第一个元素的指针的行为相同,其元素类型是对象的类型。

(注:我引用的是C 11,因为我手头没有C 03。我相当确定没有什么变化。)

所以是的,<代码>

 类似资料: