以下是否会在第4行和/或第5行中引发未定义的行为:
#include <stdio.h>
int main(void)
{
char s[] = "foo";
char * p = s - 1; /* line 4 */
printf("%s\n", p + 1); /* line 5 */
return 0;
}
答案 0 :(得分:17)
在数组范围外递减指针是未定义的。
C99 standard项目6.5.6第8段部分说明
当指针中添加或减去具有整数类型的表达式时, result具有指针操作数的类型。 ......如果两个指针 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定。
所以你的第4行正在调用未定义的行为,因为结果既不在数组中,也不在结束之前。
答案 1 :(得分:10)
是第4行是未定义的行为!
C99 6.5.6加法运算符,第8节
当指针中添加或减去具有整数类型的表达式时, result具有指针操作数的类型。如果指针操作数指向的元素 一个数组对象,并且该数组足够大,结果指向一个偏移的元素 原始元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。换句话说,如果表达式P指向数组对象的
i-th
元素,则表达式(P) + N
(等效地,N + (P)
)和(P) - N
(其中N
}值n
)分别指向数组对象的i+n-th
和i−n-th
元素,前提是它们存在。此外,如果表达式P
指向数组对象的最后一个元素,则表达式(P) + 1
指向数组对象的最后一个元素之后,如果表达式Q
指向一个数组对象的最后一个元素,表达式(Q) - 1
指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*
运算符的操作数。
答案 2 :(得分:8)
以下是否会在第4行和/或第5行中引发未定义的行为:
是的,第4行是undefined behavior,因为指针没有指向数组范围内,也没有超出数组范围。虽然指出一个超过数组边界是有效的,但是你不能取消引用该元素。
c99 draft standard中的相关部分为6.5.6
添加剂操作符第8段:
当指针中添加或减去具有整数类型的表达式时, result具有指针操作数的类型。 [...]如果指针操作数和结果指向同一数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。
段落的末尾说你不应该尊重最后一个要素:
[...]如果结果指向一个数组对象的最后一个元素,那么不应该被用作被评估的一元*运算符的操作数