单字节关闭指针在C中仍然有效?

我可能会弄错,但我似乎记得对于给定的内存分配,例如

char *p = malloc(4); 

指针p是分配中所有字节以及超出该分配的第一个字节的有效指针。

因此,通过指针p访问存储器只有偏移p[0] .. p[3]有效。 但是对于指针比较&( p[4] )也将是一个有效的指针。

这是正确的吗?C标准( 链接 )中的位置是这样说的吗? 似乎6.5.9 p6可能暗示正确的答案方向,但它仍然有点模糊。

这个答案假设pchar *

但是对于指针比较&(p [4])也是有效的。

指针p + 4 (或&( p[4] )对于与p + N进行比较,当N在{0,1,2,3,4}中与<<=== 。在C11 6.5.8:5:

比较两个指针时,结果取决于指向的对象的地址空间中的相对位置。 如果两个指向对象类型的指针都指向同一个对象,或者两个指针都指向同一个数组对象的最后一个元素,则它们相等。 如果指向的对象是同一聚合对象的成员,则指向稍后声明的结构成员的指针比指向结构中先前声明的成员的指针大,指向具有较大下标值的数组元素的指针比指向同一数组的元素的指针大。具有较低的下标值。 指向同一union对象成员的所有指针都比较相等。 如果表达式P指向数组对象的元素并且表达式Q指向同一数组对象的最后一个元素,则指针表达式Q + 1比较大于P.在所有其他情况下,行为是未定义的。

但是, p+4无效用于与==比较,例如&X ,其中X是另一个变量。 这是(最好的我的C标准解密)未指定的行为。 (当然,没有一个p + N对于与<= to &X进行比较是有效的。)

两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针和在其开头的子对象)或函数,两者都是指向同一数组的最后一个元素之后的指针object,或者一个指向一个数组对象末尾的指针,另一个指向另一个数组对象的开头,该数组对象恰好跟随地址空间中的第一个数组对象.109)

109)两个对象在存储器中可能是相邻的,因为它们是较大arrays的相邻元素或结构的相邻成员,它们之间没有填充,或者因为实现选择放置它们,即使它们是不相关的。 如果先前的无效指针操作(例如数组边界外的访问)产生了未定义的行为,则后续比较也会产生未定义的行为。

(C11 6.5.9:6)

严格来说,标准似乎没有说任何地方p + 4 == NULL被定义( 编辑:正如rici指出的那样, p + 4等于q的唯一允许是q如果q是“a的开头”紧接着发生的不同数组对象......“。由于NULL不是任何对象的地址,因此p + 4 == NULL为false。

这篇博文在C中查看了这个和其他指针比较。

&p[4]p + 4是一个有效的指针,但它不能被解除。

C11 6.5.6加法运算符

[…]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。 如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数。