c - 哪些 C 编译器有指针减法下溢?

标签 c arrays pointers compiler-construction pointer-arithmetic

所以,正如我从 Michael Burr 中了解到的那样对 this answer 的评论,C 标准不支持从数组中第一个元素之后的指针进行整数减法(我想这包括任何分配的内存)。

来自 the combined C99 + TC1 + TC2 的第 6.5.6 节(pdf):

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

我喜欢指针运算,但这从来不是我之前担心的事情。我一直假设给定:

 int a[1];
 int * b = a - 3;
 int * c = b + 3;

c == a

所以虽然我相信我以前做过那种事,而且没有被咬,但这一定是由于与我共事过的各种编译器的友善 - 他们已经超越了标准要求使指针运算按照我认为的方式工作。

所以我的问题是,这种情况有多普遍?是否有常用的编译器对我不友好?超出数组边界的正确指针运算是事实上的标准吗?

最佳答案

MSDOS FAR 指针有这样的问题,通常通过在实模式中“巧妙”使用段寄存器与偏移寄存器的重叠来解决。结果是 16 位段左移 4 位,并添加到 16 位偏移量中,得到 20 位物理地址,可以寻址 1MB,这已经足够了,因为每个人都知道没有人会需要多达 640KB 的 RAM。 ;-)

在保护模式下,段寄存器实际上是内存描述符表的索引。典型的 DOS 扩展运行时通常会安排一些事情,以便许多段可以像在实模式下一样处理,这使得从实模式移植代码变得容易。但它有一些缺陷。首先,分配之前 的段不是分配的一部分,因此它的描述符甚至可能无效。

在保护模式下的 80286 上,只要加载一个段寄存器的值会导致加载无效的描述符,就会导致异常,无论该描述符是否实际用于引用内存。

分配后的一个字节可能会发生类似的问题。指针上的最后一个++ 可能已转移到段寄存器,导致它加载新的描述符。在这种情况下,期望内存分配器可以在分配范围末尾之后安排 一个 安全描述符是合理的,但期望它安排更多的安全描述符是不合理的。

关于c - 哪些 C 编译器有指针减法下溢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/784764/

相关文章:

指针递增的 C 运算符优先级

c - 使用指针返回 vector 的好方法

c - 为什么这个 C 结构体代码可以工作?

java - 将 x 和 y 数组转换为 Point

c - 增加内存地址如何影响指针

c - C 中的数据存储被多个文件使用

转换为 (char) 并分配给 (int) 不会清除 MSB

java - 需要帮助查明 Java 遗传算法单点交叉机制中的问题

php - 将数组从 MySQL JOIN(有重复项)转换为嵌套关联数组

c - 如何在 C 中的数组中有一个变量索引