我问自己这些代码行是否会在C和C ++中产生未定义的行为。 我试图回答每一点,阅读标准关于数组下标的内容(C 6.5.6 - 8)。我没有发布整段,因为它很长。
此外,如果表达式
P
指向最后一个 数组对象的元素,表达式(P)+1
指向一个超过最后一个元素的元素 数组对象,如果表达式Q
指向一个数组对象的最后一个元素, 表达式(Q)-1
指向数组对象的最后一个元素。如果两个指针 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定义。如果结果指向一个超过数组>对象的最后一个元素,那么它 不得用作被评估的一元*
运算符的操作数。
1 int a[10];
2 int b = a[9]; // ok
3 int c = a[10]; // UB
4 int* d = (a + 10); // ok
5 int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not deferenced), // UB in pre C99
6 int* f = &a[11]; // ok from C99, UB in pre c99
int* g = a;
7 int* h = g + 15; // ok
我认为相同的aswers应该对C ++有效
这些行在C和C ++中是否有效,我误解了标准吗?
答案 0 :(得分:4)
6和7都不是有效的,因为它们不在现有数组内执行指针运算(包括一个过去的指针)。其他一切基本上都是正确的。
仅限C:假设a[i]
与*(a + i)
相同,而&*p
始终只是p
而不评估*p
,则5应该始终没问题虽然你是对的,C89没有指定这个,但这只是在C99中添加的。 (在C ++中根本不是这样,运算符可能会被重载,并且没有提到将&
和*
组合在一起。)
从n1570(草案到C11),6.5.6添加剂操作符的第8段:
[...]如果指针操作数和[
P + N
]的结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。 [...]
C ++包含非常相似的措辞(例如C ++ 11,5.7 / 5)。