下标运算符不会发生无符号下溢,为什么?

问题描述 投票:0回答:2

我一直认为下一个例子是未定义的行为(访问数组越界):

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

为什么下标运算符不会发生下溢?

c++ integer-overflow
2个回答
1
投票

为什么下标运算符不会发生下溢?

printf("%d\n", a[-1]);
具有定义的行为。指针算术适用于任何整数类型,因此
signed int
-1
会添加到
a
,从而对已初始化的元素进行界内访问。

printf("%d\n", a[index - 1]);
具有未定义的行为。
index - 1
是混合秩积分表达式,且
unsigned long
的秩高于
int
,因此它是无符号表达式,相当于
std::numeric_limits<unsigned long>::max()
。将其添加到
a
超出范围,因此是未定义的行为。由于该标准对观察到的行为没有提出任何要求,因此打印 100 是符合要求的。

printf("%ul\n", index - 1);
具有未定义的行为。
lu
是 unsigned long 的正确格式说明符。


0
投票

这是 MSVC 文档 的摘录

语法

postfix-expression [ expression ]

通常,postfix-expression表示的值是指针值,例如数组标识符,expression是整型值(包括枚举类型)。

下标被视为 int。即使

index - 1
下溢并等于
0xFFFFFFFF
,转换为 int 时也是
-1
,与 a[-1] 具有相同的效果。

© www.soinside.com 2019 - 2024. All rights reserved.