数组的C指针算术

eri*_*sse 7 c arrays math pointers

我正在阅读K&R中关于阵列算术的部分,并且遇到了一些奇怪的事情.我发布了整个段落的上下文,但我主要关注大胆的部分.

如果p和q指向同一个数组的成员,则= =,!=,<,> =等关系可以正常工作.例如,如果p指向数组的早期成员而不是q,则p <q为真.任何指针都可以有意义地与零相等或不等式进行比较.但是对于算术或与不指向同一数组成员的指针进行比较的行为是未定义的.(有一个例外:超过数组末尾的第一个元素的地址可用于指针算法.)

这个例外的原因是什么?在定义大小时,是否将额外的内存分配给任何数组的末尾?如果是这样,为了什么目的?是用空字符结束数组吗?

oua*_*uah 8

原因是你可以在循环中增加指针,如下所示:

char a[42], *p;

for (p = a; p < &a[sizeof a]; p++)  // or p != &a[sizeof a]
{
   /* ... */
}
Run Code Online (Sandbox Code Playgroud)

如果没有额外的规则,这将是未定义的行为,因为指针将无效.


jas*_*son 6

定义数组大小时,是否将额外的内存分配给任何数组的末尾?

不。您引用的上下文很重要。您加粗的例外是指指针算术(和关系)。这是说,如果您在指向同一数组成员的指针之间进行指针关系,那么您将得到udb。但是,有一个例外,即如果任何一个指针指向数组末尾的第一个元素。

如果是,目的是什么?

null 回答,因为它假定一个错误的前提。

是否以空字符结束数组?

不。

这样做的原因是,与数组末尾的比较是合法的,即与&a[sizeof a]whena是数组的比较。请注意,这&a[sizeof a]是数组末尾的第一个元素。如果p是指向a数组末尾元素或第一个元素的指针,则p可以与 进行比较&a[sizeof a]

我引用了C99 规范的第 6.5.8.5 节。

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