远指针和近指针有什么区别?

Mad*_*han 49 c pointers

谁能告诉我C中的far指针和near指针之间的区别?

Mic*_*kis 42

在16位x86分段存储器架构上,四个寄存器用于指代各自的段:

  • DS→数据段
  • CS→代码段
  • SS→堆栈段
  • ES→额外细分

编写此体系结构的逻辑地址segment:offset.现在回答这个问题:

  • 近指针指向当前段(作为偏移量).

  • 远指针使用段信息和偏移量来指向段.因此,要使用它们,必须将DS或CS更改为指定值,将取消引用内存,然后恢复DS/CS的原始值.请注意,它们上的指针算法不会修改指针的段部分,因此溢出偏移量只会将其包裹起来.

  • 然后有巨大的指针,它们被规范化以具有给定地址的最高可能段(与远指针相反).

在32位和64位体系结构中,内存模型使用不同的段,或者根本不使用段.

  • 如果你解释一个段(和一个段的偏移)是什么,这将更清楚.DOS使用的"细分"有点神秘,imho. (6认同)

Lun*_*din 36

由于没有人提到DOS,让我们忘记旧的DOS PC电脑,并从一般的观点来看待这一点.然后,非常简化,它是这样的:


任何CPU都有一个数据总线,这是CPU在一条指令中可以处理的最大数据量,即等于其寄存器的大小.数据总线宽度以位:8位,或16位或64位等表示.这是术语"64位CPU"的来源 - 它指的是数据总线.

任何CPU都有一个地址总线,也有一个以位表示的某个总线宽度.CPU可以直接访问的计算机中的任何存储器单元都具有唯一的地址.地址总线足够大,可以覆盖您拥有的所有可寻址内存.

例如,如果计算机具有65536字节的可寻址内存,则可以使用16位地址总线覆盖这些内存,2 ^ 16 = 65536.

大多数情况下,但并非总是如此,数据总线宽度与地址总线宽度一样宽.如果它们具有相同的大小是很好的,因为它保持CPU指令集和为其编写的程序更清晰.如果CPU需要计算一个地址,那么很方便该地址是否足够小以适应CPU寄存器(通常在地址时称为索引寄存器).

非标准的关键字far,并near用于描述在需要解决的内存超出了正常的CPU地址总线宽度系统指针.

例如,具有16位数据总线的CPU也可以方便地具有16位地址总线.但是同一台计算机可能还需要超过2 ^ 16 = 65536字节= 64kb的可寻址内存.

然后,CPU通常会有特殊指令(稍微慢一些),这使得它可以处理超过64kb的内存.例如,CPU可以将其大内存划分为n 页面(有时也称为,和其他此类术语,这可能意味着从一个CPU到另一个CPU的不同),其中每个页面为64kb.然后它将有一个"页面"寄存器,必须首先设置,然后才能寻址扩展内存.类似地,当从扩展内存中的子例程调用/返回时,它将具有特殊指令.

为了使C编译器在处理这种扩展内存时生成正确的CPU指令,发明了非标准nearfar关键字.非标准,因为它们没有被C标准规定,但它们是事实上的行业标准,几乎每个编译器都以某种方式支持它们.

far指位于扩展存储器中的存储器,超出地址总线的宽度.由于它指的是地址,因此通常在声明指针时使用它.例如:int * far x;表示"给我一个指向扩展内存的指针".然后编译器将知道它应该生成访问这种内存所需的特殊指令.类似地,使用的函数指针far将生成跳转到/从扩展内存返回的特殊指令.如果你没有使用far那么你会得到一个指向正常,可寻址内存的指针,你最终会指向完全不同的东西.

near主要包括与far; 它指的是可寻址存储器中的任何东西,它等同于常规指针.所以它主要是一个无用的关键字,除了一些罕见的情况,你想确保代码放在标准的可寻址内存中.然后你可以明确标记为near.最典型的情况是低级硬件编程,您可以在其中编写中断服务程序.它们由硬件从具有固定宽度的中断向量调用,该宽度与地址总线宽度相同.这意味着中断服务程序必须位于标准可寻址存储器中.


最着名的使用farnear可能是提到的旧MS DOS PC,现在被认为是相当古老的,因此有轻微的兴趣.

但这些关键字也存在于更现代的CPU上!最值得注意的是在他们的几乎每8位和16位微控制器系列在市场上存在,因为这些微控制器通常具有16位地址总线宽度,但有时大于64KB的内存多的嵌入式系统.

每当你有一个CPU需要寻址超出地址总线宽度的内存时,你就需要farnear.一般来说,这样的解决方案是不受欢迎的,因为对它们进行编程并且总是考虑扩展内存是非常痛苦的.

推动开发64位PC的主要原因之一,实际上是32位PC已经达到其内存使用量开始达到地址总线限制的程度:它们只能解决4Gb的RAM问题.2 ^ 32 = 4,29亿字节= 4Gb.为了能够使用更多的RAM,这些选项要么采用像DOS时那样繁琐的扩展内存解决方案,要么将计算机(包括地址总线)扩展到64位.

  • "用于描述需要解决超出正常CPU地址总线宽度的内存的系统上的指针" - 不,8086具有20位地址总线.内存分段是关于在不扩大指针大小的情况下生成更宽的地址."这就是术语"64位CPU"的来源 - 它指的是数据总线." - 不,它指的是整数寄存器宽度.数据总线通常更宽,L1高速缓存能够加载128位的SIMD寄存器,更高级别的存储器层次更宽.地址巴士通常较窄; MMU可能没有64位物理地址空间. (5认同)
  • 时不时地,您会发现编写的代码非常注重可移植性,以至于它们在编译器周围工作,其中 `near` 和 `far` 仍然是关键字。所以你会发现像[带有`hither`和`yon`剪裁平面的3D投影矩阵](http://chromium.sourceforge.net/doc/stereo.html)... (2认同)

Pab*_*ruz 22

在DOS等旧平台中使用了远近指针.

我认为它们与现代平台无关.但是你可以在这里这里了解它们(正如其他答案所指出的那样).基本上,指针是扩展计算机中可寻址内存的一种方法.IE,在16位平台上处理超过64k的内存.