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

时间:2015-08-10 08:12:57

标签: c arrays pointers pointer-arithmetic

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

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

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

2 个答案:

答案 0 :(得分:13)

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

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

远指针是32位宽,由两个16位半部分组成,segmentoffset;例如1234:0000是一个具有段0x1234且偏移量为0的指针。实际内存地址为segment * 16 + offset。通常,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。它比较less than 1238:0000(因为0x1234< 0x1238)但它指向更高的地址(因为0x123C0> 0x1238)。

为什么呢?因为将128指向x,它指向一个64字节的对象,所以是未定义的行为。

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

一些内存模型让编译器总是使用远指针,如果数据+堆栈+堆超过64K("压缩"或"大"内存模型),则速度较慢但是必需的。 / p>

代码和数据的大小也不同,所以你可以有一个内存模型,其中函数指针靠近但数据指针很远,反之亦然。前面提到的" compact"模型(64K代码限制,但数据的远指针)和双重"媒体" model(代码的远指针,64K数据限制)。

还有一种方法可以让编译器为所有东西使用扁平的32位指针(所谓的"巨大的"内存模型),但它很慢并且没有人使用它。

答案 1 :(得分:5)

Undefined behavior适用于此处。你不能比较两个指针,除非它们都指向同一个对象或指向该对象结束后的第一个元素。