以下使用指针算法的语句是否有效?

时间:2016-09-19 08:00:31

标签: c arrays pointers undefined-behavior pointer-arithmetic

char array[8] = "Raining";

我认为以下所有相关陈述的评论都符合我的理解。

char *p1 = array + 7;      --> points to '\0'

char *p2 = array + 8;      --> undefined behaviour

char *p3 = array + 9;      --> undefined behaviour

char *p4 = array + 10;     --> undefined behaviour

我的理解是否正确?

3 个答案:

答案 0 :(得分:14)

在你的情况下,

  char *p1 = array + 7;

  char *p2 = array + 8;

有效,因为您在法律上可以指向

  • 数组长度内的任何对象
  • 一个超过最后一个数组元素,直到您取消引用它

OTOH,

  char *p3 = array + 9;

  char *p4 = array + 10; 

未定义。

引用C11,章节§6.5.6,“添加运算符”(强调我的

[同样在 C99章节§6.5.6/ p8,感兴趣的任何人]

  

当指针中添加或减去具有整数类型的表达式时,   result具有指针操作数的类型。 如果指针操作数指向的元素   一个数组对象,并且该数组足够大,结果指向一个偏移的元素   原始元素使得结果和原始的下标不同   数组元素等于整数表达式。换句话说,如果表达式P指向   数组对象的i - 元素,表达式(P)+N(等效地,N+(P))和   (P)-N(其中N的值为n)分别指向i+n - 和i−n - 元素   数组对象,只要它们存在。此外,如果表达式P指向最后一个   数组对象的元素,表达式(P)+1指向一个超过最后一个元素的元素   数组对象,如果表达式Q指向一个数组对象的最后一个元素,   表达式(Q)-1指向数组对象的最后一个元素。 如果两个指针都有   操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素   数组对象的元素,评估不得产生溢出;否则,   行为未定义。 [...]

答案 1 :(得分:5)

由于NULL终止符,

apiCall main java.lang.Exception at test.TestMain.apiCall(TestMain.java:33) at test.TestMain.main(TestMain.java:25) 中有8个元素。

array定义明确。

char *p1 = array + 7;实际上是已定义。你可以设置一个指向数组的指针。 (只是不要取消引用它。)

其他两个未定义。你不允许在数组之外设置指针。

答案 2 :(得分:4)

第一行指向数组内的合法元素,第二行在解除引用之前有效。你的帖子的其余部分是正确的。

char *p1 = array + 7;   \\-->points to '\0', within array

char *p2 = array + 8;   \\-->defined behaviour until dereferenced 

允许 past-the-end 寻址的原因是可以轻松编写循环来遍历整个数组,例如while(*d++ = *s++);

enter image description here

数组的边界标记描述半开范围,从(包括)第一个元素开始,以(但不包括)最后一个元素结束:[beginning,end)