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

为何C++下标运算符中未发生无符号下溢?

关于这段C++代码的疑问解析

先贴出你提到的代码和运行结果:

示例代码

int main()
{
    int* a= new int[3];
    a[0] = 100;
    a++;
    
    unsigned long index = 0;
    
    printf("%d\n", a[-1]);
    printf("%d\n", a[index - 1]);
    printf("%ul\n", index - 1);
}

运行输出

100
100
4294967295l

首先澄清第一个误解:a[-1]并不是数组越界。a在执行a++后指向数组的第二个元素,a[-1]等价于*(a - 1),这个指针指向的是原数组的第一个元素(合法存在的a[0]),所以解引用能得到100是完全正常的。

接下来解释你最疑惑的点:为什么a[index - 1]没有因为无符号下溢出现越界?

核心原因:隐式类型转换的巧合

C++中,指针与整数进行加法运算时,整数操作数会被隐式转换为ptrdiff_t类型——这是一个专门用于表示指针差值的有符号整数类型。

  • index是unsigned long类型,index - 1会触发无符号整数的溢出规则,结果是ULONG_MAX(也就是输出里的4294967295)。
  • 在32位系统中,ptrdiff_t是32位有符号整数,ULONG_MAX(二进制全1)按照补码规则转换为有符号整数时,结果就是-1。
  • 于是a + (index - 1)就等价于a + (-1),也就是a - 1,解引用自然得到原数组的第一个元素100。

必须强调:这是未定义行为

你看到的正常输出只是特定环境下的巧合,这段代码里的a[index - 1]本质属于标准未定义行为:

  • C++标准并没有规定无符号整数超出ptrdiff_t范围时的转换结果,只是多数编译器在补码系统下会按上述逻辑处理。
  • 如果切换到64位系统,ptrdiff_t是64位有符号整数,此时ULONG_MAX(64位下是18446744073709551615)超出了有符号整数的最大值,转换结果是未定义的,这时a[index - 1]很可能真的变成越界访问,导致崩溃或随机结果。

简言之,这种“正常输出”不能作为代码正确的依据,本质上还是依赖了未定义的编译器行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:07:44