为什么在 C 中不允许在数组的第一个元素之前指向一个?

Pab*_*ias 5 c arrays pointers

在 C 中,指针可以指向数组的任何元素,也可以指向数组最后一个元素之后的元素;指向超出此范围的行为是未定义的行为(C11 标准,第 6.5.6 节,第 8 段)。

但是,为什么同样不允许在数组的第一个元素之前指向一个?

PS:我知道,为了规避上述限制,有时可以声明一个比需要大1个单位的数组,然后只使用从1开始的位置来存储元素,最后保留位置0作为遍历数组的保证向后将是安全的。但是,有时我们必须使用给定的数组,然后在第一个元素之前指向一个的问题仍然存在。

Ste*_*ner 3

“允许指针指向数组的任何元素”这一主题长期以来一直是 C 语言的一部分;它已经可以在ANSI-C 标准/C89中找到(参见第 6.3.6 节加法运算符,第 46f 页),其中已经提到在此范围内的实现必须防止算术溢出。其中,在第47页的最后,还可以找到一个脚注,解释其背后的原理:

进行指针算术的另一种方法是首先将指针转换为字符指针:在此方案中,与转换后的指针相加或相减的整数表达式首先乘以原始指向的对象的大小,所得指针为转换回原始类型。对于指针减法,字符指针之间的差异的结果类似地除以最初指向的对象的大小。

以这种方式来看,实现只需要在对象末尾之后提供一个额外的字节(可能与程序中的另一个对象重叠),以满足“最后一个元素后一个”的要求

由此我们可以推断出原因是防止算术溢出,这是一种实现必须在数组和过去的范围内避免的情况(但这显然不需要保证)数组第一个元素之前的元素)。

为什么不是之前的一个 - 可能(我没有证明)与以下事实有关:指针范围可能仅限于特定的内存段,并将对象与诸如“第一个元素之前的一个”之类的算术一起放置在内存段的开头" 可能会导致溢出。我想说, “实现只需要在对象结束后提供一个额外的字节(可能与程序中的另一个对象重叠)”是支持这一假设的明确指标,因为此时的标准明确解决了“一个额外字节”主题位于末尾,但没有建议内存段的开头类似的内容。