c - 为什么我们不能比较不指向同一数组中元素的指针?

标签 c arrays pointers pointer-arithmetic

我一直在学习 C 语言并遵循 Yashavant P. Kanetkar 的“Let Us C”。

指针章节中有一行说我们只能比较即小于 (<) 和大于 (>) 指向同一数组中元素的指针。

为什么比较任意指针无效?

最佳答案

因为 C 不假设主机,也没有什么能阻止主机在两个完全独立的地址空间中分配两个数组。

It's not just about theoretical exotic architectures either . x86 机器的 16 位编译器提供了两种指针。近指针有 16 位宽并且表现得像你期望的那样;但是,它们只允许您访问 64k 的 RAM。如果您想访问超过 64k 的 RAM(不是每个 block 64K:整个程序 64K!),您必须使用远指针。

远指针为 32 位宽,由两个 16 位的一半组成,即 偏移量;例如 1234:0000 是一个指针,它有段 0x1234 和偏移量 0。实际内存地址是 段 * 16 + 偏移量。通常,farmalloc 返回一个偏移量为零的指针,指针运算仅修改偏移量。所以你可以有

 char *x = farmalloc(64);     // returns 1234:0000 for address 0x12340
 char *y = farmalloc(64);     // returns 1238:0000 for address 0x12380

现在,如果您计算 x + 128,结果是 1234:0080,地址为 0x123C0。它比较小于 1238:0000(因为 0x1234 < 0x1238)但它指向更高的地址(因为 0x123C0 > 0x1238)。

为什么?因为将 128 加到指向 64 字节对象的 x 是未定义的行为。

memory model编译器设置定义了指针的默认大小是 near 还是 far。例如,“小”内存模型有 64K 用于代码,64K 用于所有全局变量、自动变量(堆栈)和 malloc 堆。请注意,代码位于单独的段中,因此您不能只使用 16 位(“近”)函数指针并取消引用它来读取机器语言!如果您必须这样做,则必须要求编译器将代码与其余代码放在同一段中(“微型”内存模型)。

某些内存模型让编译器始终使用远指针,如果数据+堆栈+堆超过 64K(“紧凑”或“大”内存模型),这会更慢但有必要。

代码和数据的大小也不同,所以你可以有一个内存模型,其中函数指针很近而数据指针很远,反之亦然。上述“紧凑”模型(64K 代码限制,但数据远指针)和双“中等”模型(代码远指针,64K 数据限制)就是这种情况。

还有一种方法可以让编译器对所有内容使用平面 32 位指针(所谓的“巨大”内存模型),但是速度很慢而且没有人使用它。

关于c - 为什么我们不能比较不指向同一数组中元素的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31914652/

相关文章:

c++ - 未找到 BFD 库

c# - 使用从 C# 到非托管驱动程序的嵌入式指针编码结构

c - free() 不应该接受 (void *const) 作为输入参数

c - Atmega1 6's PORTs don' 工作

C中函数指针typedef的循环引用

c - 这段代码中是否存在竞争条件的可能性?

javascript - 将数组的每个项目与另一个数组的项目连接

java - float 数组到 double 数组

javascript - Angularjs 数组中的嵌套对象数组

c - 只要您永远不取消引用它,持有未对齐的指针是否定义明确?