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

ash*_*ani 5 c arrays pointers pointer-arithmetic

我一直在学习C语言,并跟随Yashavant P. Kanetkar的"Let Us C".

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

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

Que*_*tin 13

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

它不仅仅是关于理论上的异域架构.x86机器的16位编译器提供了两种指针.近指针是16位宽,表现得像你期望的那样; 但是,它们只允许您访问64k的RAM.如果你想访问超过64k的RAM(每个块不是64K:整个程序是64K!)你必须使用远指针.

远指针是32位宽,由两个16位半部分组成,segment并且offset; 例如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
Run Code Online (Sandbox Code Playgroud)

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

为什么?因为将128 x指向64字节对象的求和是未定义的行为.

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

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

代码和数据的大小也不同,所以你可以有一个内存模型,其中函数指针靠近但数据指针很远,反之亦然.前面提到的"紧凑"模型(64K代码限制但远程数据指针)和双"中"模型(代码的远指针,64K数据限制)就属于这种情况.

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

  • @ user132458你的例子假设指针是有序整数,并且所有指针都指向同一个地址空间.C不保证这些属性. (6认同)
  • @ user132458这是最终运行程序的机器. (4认同)
  • @alk我不确定这是否是今天最好或最差的建议. (2认同)
  • @ user132458的要点是,指针不总是连续的,增加整数.一些内存模型允许你获得两个指针`a`和`b`,当重新解释为整数时,它们的位将导致`a <b`,而事实上`a`更进一步.或者,您可以使用两个指针来比较近似相等,但不要指向同一个数组,因为每个指针都指向一个单独的内存段. (2认同)

Day*_*rai 5

未定义的行为适用于此处.你不能比较两个指针,除非它们都指向同一个对象或指向该对象结束后的第一个元素.