我一直认为下一个例子是未定义的行为(访问数组越界):
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
为什么下标运算符不会发生下溢?
为什么下标运算符不会发生下溢?
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 的正确格式说明符。
这是 MSVC 文档 的摘录
”
语法:
postfix-expression [ expression ]
通常,postfix-expression表示的值是指针值,例如数组标识符,expression是整型值(包括枚举类型)。
”
下标被视为 int。即使
index - 1
下溢并等于 0xFFFFFFFF
,转换为 int 时也是 -1
,与 a[-1] 具有相同的效果。