减少指针超出范围;将它增加到边界

时间:2013-08-12 12:27:47

标签: c pointers undefined-behavior

以下是否会在第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;
}

3 个答案:

答案 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-thi−n-th元素,前提是它们存在。此外,如果表达式P指向数组对象的最后一个元素,则表达式(P) + 1指向数组对象的最后一个元素之后,如果表达式Q指向一个数组对象的最后一个元素,表达式(Q) - 1指向数组对象的最后一个元素。 如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数。

答案 2 :(得分:8)

  

以下是否会在第4行和/或第5行中引发未定义的行为:

是的,第4行undefined behavior,因为指针没有指向数组范围内,也没有超出数组范围。虽然指出一个超过数组边界是有效的,但是你不能取消引用该元素。

c99 draft standard中的相关部分为6.5.6 添加剂操作符第8段

  

当指针中添加或减去具有整数类型的表达式时,   result具有指针操作数的类型。 [...]如果指针操作数和结果指向同一数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义

段落的末尾说你不应该尊重最后一个要素:

  

[...]如果结果指向一个数组对象的最后一个元素,那么不应该被用作被评估的一元*运算符的操作数