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

Gar*_*ick 4 c arrays pointers pointer-arithmetic undefined-behavior

char array[8] = "Raining";
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

我的理解是否正确?

Sou*_*osh 14

在你的情况下,

  char *p1 = array + 7;
Run Code Online (Sandbox Code Playgroud)

  char *p2 = array + 8;
Run Code Online (Sandbox Code Playgroud)

有效的,因为,法律允许你指出

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

OTOH,

  char *p3 = array + 9;
Run Code Online (Sandbox Code Playgroud)

  char *p4 = array + 10; 
Run Code Online (Sandbox Code Playgroud)

未定义.


引用C11,章节§6.5.6,"加法运算符"(强调我的)

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

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

  • "法律允许你指出一个超过最后一个数组元素,直到你取消引用它" - 真的吗?我今天学到了一些东西......(如果你或其他任何人有这个标准,我有兴趣看看标准的相关部分吗?) (3认同)
  • @PaulR:不,不是.这解释了为什么C++中的反向迭代器非常不对称的原因.(转发iterator = reversiterator.base() - 1). (3认同)
  • Upvoted.@ SouravGhosh在这里是正确的.在C和C++中允许将指针设置为超过数组*的最后一个元素*.(这是`end()`可以在C++中实现的方式). (2认同)
  • @stackuser nopes,没有.__超过最后一个数组___就是这样.期. (2认同)
  • @SouravGhosh:很酷 - 感谢您对C99标准的额外参考.现在我很好奇是否在第一个元素*之前指向*一个元素也可能是有效的,出于同样的原因,但是对于反向迭代的循环的用例? (2认同)

Bat*_*eba 5

array 由于NULL终止符,它有8个元素.

char *p1 = array + 7; 定义明确.

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

另外两个是未定义的.你不允许将指针设置在数组之外.

  • @stackuser如果您有兴趣,我已将报价添加到我的版本中.:) (2认同)