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

有人可以告诉我C中的far指针和near指针之间的区别吗?

Madhan asked 2020-02-20T01:10:14Z
6个解决方案
42 votes

在16位x86分段存储器体系结构上,使用四个寄存器来引用各自的段:

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

该体系结构的逻辑地址写为segment:offset。现在回答这个问题:

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

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

  • 然后是巨大的指针,这些指针被规范化为具有给定地址的最大分段(与远指针相反)。

在32位和64位体系结构上,内存模型使用的段不同或完全不同。

Michael Foukarakis answered 2020-02-20T01:11:03Z
35 votes

由于没有人提到DOS,因此让我们忘记旧的DOS PC计算机,并从一般的角度来看待它。 然后,非常简化,它是这样的:


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

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

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

通常,但并非总是如此,数据总线宽度与地址总线宽度一样宽。 如果它们的大小相同,那就太好了,因为这样可以使CPU指令集和为其编写的程序更加清晰。 如果CPU需要计算地址,则该地址足够小以适合CPU寄存器(当涉及到地址时通常称为索引寄存器)可以方便使用。

非标准关键字farnear用于描述系统上的指针,在这些指针上,您需要对超出正常CPU地址总线宽度的内存进行寻址。

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

然后,CPU通常会有特殊的指令(速度稍慢),这使它可以处理超过64kb的内存。 例如,CPU可以将其大内存划分为far页(有时也称为存储体,段和其他此类术语,可能意味着一个CPU与另一个CPU的含义不同),其中每个页面为64kB。 然后它将有一个“页面”寄存器,在寻址该扩展存储器之前,必须首先设置该页面。 同样,从扩展内存中的子例程调用/返回时,它将具有特殊的指令。

为了使C编译器在处理此类扩展内存时生成正确的CPU指令,发明了非标准的farnear关键字。 非标准不是C标准指定的,但是它们实际上是行业标准,几乎每个编译器都以某种方式支持它们。

far指的是位于扩展内存中,超出地址总线宽度的内存。 由于它引用地址,因此在声明指针时经常使用它。 例如:near的意思是“给我一个指向扩展内存的指针”。 然后,编译器将知道应该生成访问此类内存所需的特殊指令。 同样,使用near的函数指针将生成特殊指令以跳转到扩展内存或从扩展内存返回。 如果您不使用far,那么您将获得一个指向普通可寻址内存的指针,并且最终将指向完全不同的东西。

主要包括far,以与near保持一致; 它引用可寻址内存中的任何内容,等同于常规指针。 因此,它主要是一个无用的关键字,除了在极少数情况下要确保将代码放置在标准可寻址内存中的情况下。 然后,您可以将其明确标记为near。最典型的情况是在底层硬件编程中编写中断服务程序。 硬件从固定宽度的中断向量调用它们,该宽度与地址总线宽度相同。 这意味着中断服务程序必须位于标准可寻址存储器中。


farnear最著名的用途可能是所提到的旧MS DOS PC,如今它被认为是非常古老的,因此兴趣不大。

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

每当有需要在地址总线宽度以外的地址进行寻址的CPU时,就需要farnear。通常,此类解决方案不受欢迎,因为在它们上进行编程非常麻烦,并且始终采用 帐户中的扩展内存。

推动开发64位PC的主要原因之一实际上是32位PC的内存使用量开始达到地址总线极限:它们只能寻址4GB的RAM。 2 ^ 32 = 42.9十亿字节= 4GB 为了能够使用更多的RAM,然后选择使用某些麻烦的扩展内存解决方案(例如在DOS时代),或者将计算机(包括其地址总线)扩展到64位。

Lundin answered 2020-02-20T01:12:33Z
22 votes

远近指针已在DOS等旧平台中使用。

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

Pablo Santa Cruz answered 2020-02-20T01:12:58Z
4 votes

指针基本上保存地址。 众所周知,英特尔内存管理分为四个部分。因此,当指针指向的地址在同一段内时,它是近指针,因此它仅需要2个字节的偏移量。另一方面,当指针指向该段之外的地址(即在另一个段中)时,该指针就是一个远指针。 它由4个字节组成:两个用于段,两个用于偏移量。

aman singh bhandari answered 2020-02-20T01:13:19Z
0 votes

四个寄存器用于引用16位x86分段存储器体系结构上的四个段。 DS(数据段),CS(代码段),SS(堆栈段)和ES(额外段)。 在此平台上的逻辑地址以十六进制形式写入segment:offset。

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

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

然后是巨大的指针,这些指针被规范化为具有给定地址的最大分段(与远指针相反)。

在32位和64位体系结构上,内存模型使用的段不同或完全不同。

dharam raj answered 2020-02-20T01:13:57Z
0 votes

在DOS中,处理寄存器有点有趣。 和细分。 关于RAM的最大计数容量。

今天,这几乎是无关紧要的。 您需要阅读的只是虚拟/用户空间和内核的区别。

自从赢得nt4以来(当他们从* nix窃取想法时),Microsoft程序员开始使用所谓的用户/内核内存空间。从那时起,避免直接访问物理控制器。 从那以后,这个问题也就解决了直接访问内存段的问题。 -一切都通过OS变成了R / W。

但是,如果您坚持理解和处理远近指针,请查看linux内核源代码及其工作方式-我猜您会更新。

并且如果您仍然需要在DOS中使用CS(代码段)/ DS(数据段)。 看看这些:

[HTTPS://恩.Wikipedia.org/wiki/Intel_memory_model][HTTP://呜呜呜.digital Mars.com/床头柜/床头柜memory model.HTML]

我想指出下面的完美答案..来自伦丁。 我懒得回答不正确。 隆丁非常详细,明智地解释了“竖起大拇指”!

Oskars Lusis answered 2020-02-20T01:14:45Z
translate from https://stackoverflow.com:/questions/1749904/what-is-the-difference-between-far-pointers-and-near-pointers