near、far、huge三个指针的区别

1、近(near)指针

   近指针是16位指针,它只含有地址的偏移量部分,当用汇编语言和C语言混合编程时,汇编语言总是假设DS含有数据目标的地址。虽然近指针占用空间最小,执行速度最

快,但它有一个严格的限制, 即只能64K字节以内的数据,且只能存取程序的数据段内的数据。 如果在小模式下编译一个程序,而这个程序企图增量一个近指针使之超过第

65536个字节,则这个近的指针就会复位到0。

下面就是这样一个例子:   

 char _near *p=(char _near *)0xffff;   

 p++;   

 由于近指针的这个严重限制,所有在比较大或比较复杂的程序中,都无法使用。

2、远(far)指针

  远指针是把指针的段地址与指针的偏移量直接存放在指针内,远指针是由4 个字节构成。它可以指向内存中的任一目标,可以用于任一编译模式,尽管仅在紧凑、大和巨模

下远指针才是缺省的数据指针。应该注意:尽管远指针可以寻址内存中的任一单元,但它所寻址的目标也不能超过64K字节。这是因为,远指针在增量或减量之类的算术运算

时,也只是偏移量部分参与运算,而段地址保持不变。因此,当远指针增量或减量到超过64K字节段边界时就出错。

例如: 

  char far *fp=(char far *)0xb800ffff; 

  fp++; 在指针加1以后,fp将指向B800:0000,而不是所希望的 C800:0000。   

 此外,在进行指针比较时,far指针还会引起另外一些问题。far 指针是由偏移量和段地址这样一对16位数来表示的,对于某一实际内存地址,far指针不是唯一的,

 例如,far指针1234:0005、1230:0045、1200:0345、1000:2345、0900:9345等都是代表实际地址12345,这样 会引起许多麻烦。   

  第一,为了便于与“空”(NULL)指针(0000:   0000)进行比较,当关系操作符“==”和“!=”用于对far   指针进行比较时,比较的是全部32位。否则,如果只比较16位

偏移量,那么任何偏移量为0   的指针都将是“空”(NULL)指针,这显然不符合一般使用要求。但在进行这32位比较时,不是按20位实际地址来比较,而是把段地址和偏移量

当作一个32位无符号长整数来比较。对于上面这个例子,假设这些指针分别叫作a、b、c、d、e,尽管这5个far   指针指向的都是同一内存单元,但下列表达式运算的结果却

都为“假”,从而得出错误的结论:   

  if(a==b)....   
  if(b==c)....   
  if(c==d)....   
  if(d==e)....   
  if(a==c)....   
  if(a==d)....   

  第二,当用“>”、“>=”,“<”和“<=”关系操作符对指针进 行比较操作时,比较的仅仅是偏移量部分,即按无符号的16位整数进行比较。因此,对于上面这个例子,

列表达式运算的结果将都为“真”,也得出错误的结论:   

  if(e>d)....   
  if(d>c)....   
  if(c>b)....   
  if(b>a)....   
  if(e>a)....

3 巨(huge)指针

  只有巨指针才是一般C语言教科书上所说的指针,它像远指针也占4个字节。与远指针的显著差别是:当增量或减量超过64K字节段边界时,巨指针会自动修正段基址的值。

此,巨指针不但可以寻址内存中的任一区域,而且所寻址的数据目标可以超过64K字节。

例如:   

  char huge *hp=(char huge *)0xb800ffff;   

  hp++;   

  在指针加1后,hp将指向C800:0000。但是,巨指针总是比较慢的,因为编译必须生成一小段程序对指针进行32位而不是16位的加减运算。此外,由于huge指针是规则化指

针,每一个实际内存地址只一个 huge指针,所有在指针比较时不会产生错误。

4 基(based)指针

 前面已经说过,巨指针综合了近指针和远指针的优点。像近指针一样,基指针只占两个字节,这两个字节是地址的偏移量。像远指针一样,基指针可以寻址内存中的任一区

域。近指针的段地址隐含地取自程序的数据段,远指针的段地址取自指针本身。  

5 各类指针之间的转换   

  far指针可以强制转换为near指针,做法很简单,抛掉段地址只保留偏移量。near指针也可以转换为far指针,TurboC的做法是从相应的段寄存器中取得段地址。

far指针有时也需要转换为huge指针,以便对指针进行比较或做其它操作。

一种方法是通过下面这样一个规则化函数:  

 void normalize(void far **p)   {   

  *p=(void far *)(((long)*p^0xffff000f)+   

  (((long)*p^0x0000fff0)<<12));   

  }   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值