You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

指向数组末尾之后位置的C++指针代码是否符合标准?

关于C++数组指针越界的标准合规性与运行问题解答

先贴出你提供的代码:

#include <iostream>

int main()
{
   int arr[4]{0,1,2,3};
   int* begin = arr;
   int *end = &arr[4];
   int *firstElement = &arr[1];
   int *lastElement = &arr[3];
   int *onePastEnd = &arr[5];
   std::cout << firstElement - begin << std::endl; //outputs 1
   std::cout << lastElement - begin << std::endl; //outputs 3
   std::cout << end - begin << std::endl; //outputs 4
   std::cout << onePastEnd - begin << std::endl; //outputs 5
   //std::cout << (*(firstElement - begin)); //illegal indirection because you're trying to find out what is at an address, but this is not an address rather difference between two pointers
}

1. 代码是否符合C++标准?

要分两种情况明确:

  • &arr[4]是符合标准的:C++标准允许创建指向数组最后一个元素之后一个位置的指针(俗称“one past the end”指针),这个指针可用于标记范围边界(比如和起始指针配合计算元素个数),但注意该指针绝对不能被解引用。
  • &arr[5]完全不符合标准:数组arr仅含4个元素,合法索引为0~3。arr[5]本身属于越界访问,获取它的地址属于创建超出允许范围的指针,直接违反C++标准,属于未定义行为。
    另外,onePastEnd - begin这个指针减法操作也属于未定义行为,因为onePastEnd是非法指针,标准仅允许指向同一数组(或其one past the end位置)的指针做减法运算。

2. 为何代码能“正常运行”?

未定义行为的核心是C++标准不对其行为做任何承诺,这段代码能运行只是巧合:

  • 从内存布局看,数组arr位于栈上,它后面的地址可能是栈上的空闲空间或其他变量内存,当前程序访问这些地址时没有触发内存错误(比如段错误)。
  • 默认优化等级下,多数编译器不会主动检测这类越界指针的创建,因此代码能通过编译并运行。

但这种“正常”完全不可靠,更换编译器、调整优化等级、修改程序其他部分,都可能导致程序崩溃、输出错误结果,甚至出现更诡异的行为,绝对不能依赖未定义行为的表现。

内容的提问来源于stack exchange,提问作者ZoomIn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:57:21