far指针与near指针

win16、win32相关知识:

运行在16位CPU(80826微处理器)微机上的Windows16,对于内存按照“分段内存模式”(Segment Memory Mode)进行使用.在DOS下(实模式)地址是分段的,每一段的长度为64K字节,刚好是16位(二进制的十六位)。

16位CPU(主要指80386和80486)内部数组总线为16位,地址总线为24位。这就意味着一个字(16bit)存不下一个地址,要用到两个字。习惯把高位字称为段地址,低位字称为偏移地址。
Windows 95开始的32位机上,支持32位平面内存模式,为Win32写的程序使用32位的线性地址空间。
只有在win16上,才会设计到near、far指针的概念。在win32上,并没有此区别。

程序运行时,OS会给程序分配几个内存段供程序使用,主要的有代码段(CS)、数据段(DS)、堆栈段(SS)。根据不同的编译模式这几个段可能重合。
当指针指向的地址与数据段的段地址相同(即处于数据段内),这时可以不记录段地址而仅记录偏移地址(只需16bit)。这种指针称为近指针(near指针)。
当指针指向的地址与数据段的段地址不同(即处于数据段外),这里不仅要记录偏移地址还要记录段地址(共需32bit)。这种指针称为远指针(far指针)。

在DOS下(实模式)地址是分段的,每一段的长度为64K字节,刚好是16位(二进制的十六位)。
near指针的长度是16位的,所以可指向的地址范围是64K字节,通常说near指针的寻址范围是64K。
far指针的长度是32位,含有一个16位的基地址和16位的偏移量,将基地址乘以16后再与偏移量相加,(所以实际上far指针是20位的长度)即可得到far指针的1M字节的偏移量。所以far指针的寻址范围是1M字节,超过了一个段64K的容量。例如一个far指针的段地址为0x7000,偏移量为0x1244,则该指针指向地址0x71224,如果一个far指针的段地址是0x7122,偏移量为0x0004,则该指针也指向地址0x71224

存储属性:
near指针:16位段内偏移地址 
far指针:16位段地址+16位段内偏移地址 
huge指针:32位规格化的具有唯一性的内存地址 
C语言的存贮属性由六种编译模式决定(参见TC集成环境菜单中的option->compiler->model选项),默认的编译模式为small,在该编译模式下,指针的默认属性为near。所以far指针要显式指定。

near关键字:

near关键字创建一个指向可寻址内存低端部分的目标指针,是16位指针,依赖一个段地址寄存器,这些指针占用内存的单一字节,能够指向的内存单元被限制到256个位置,通常是在 0x0000~0x00ff范围中,指针变量就是位移量,利用段地址寄存器+指针来寻址,所以有64K之限制。对于数据指针,在微小和中编译模式下产生的数据指针是近指针,因为此时只有一个不超过64K 字节的数据段。对于码(即函数指针)指针,在微小和紧凑编译模式下产生的码指针是近指针,因为此时只一个不超过 64K字节的码段。为了形成32位 的完整地址,编译程序一般是反近指针与程序的数据段的段地址组合起来。虽然近指针占用空间最小,执行速度最快,但它有一个严格的限制,只能存取程序的数据段内的数据。如果在小模式下编译一个程序,而这个程序企图增量一个近指针使之 超过第65536个字节,则这个近指针就会复位到0.  如:

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

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

far关键字:

far关键字创建一个能够指向内存中任何数据的指针,是32位指针,不但有16位的位移量,还有16位的段地址,但此指针有个缺陷,增量时只加到位移部分,一旦16位的位移量超过了FFFF就会回到这个段地址的初始。例如一个far指针的段地址为0x7000,偏移量为0x1244,则该指针指向地址0x71224. far指针要显式指定,工作起来要慢一些,因为每次访问一个far指针时,都要将数据段或程序段的数据交换出来。另外,far指针的运算也比较反常,例如上面讲到的far指针指向同一个地址,但是比较的结果却不相同。许多库函数就是显式地指定为far函数的形式。far指针通常和farmalloc()这样的内存分配函数一起使用。每次使用远指针时都需要重新装载段寄存器,这显然会降低速 度。应该注意:尽管远指针可以寻址内存中的任一单元,但它所寻址的目标也不能超过64K字节。这是因为,远指针在增量或减量之类的 算术运时,也只是偏移量部分参与运算,而段地址保持不变。因此,当远指针增量或减量到超过64K字节段边界时就出错。
例如:

 char far * fp=(char far *)0xb800ffff;   fp++;  //在指针加1以后,fp将指向B800:0000,而不是所希望的 C800:0000。  

什么时候使用far指针?
当使用小代码或小数据存储模式时,不能编译一个有很多代码或数据的程序。因为在64K的一个段中,不能放下所有的代码与数据。为了解决这个问题,需要指定以far函数或far指针来使用这部分的空间(64K以外的空间)。许多库函数就是显式地指定为far函数的形式。far指针通常和farmalloc()这样的内存分配函数一起使用。

此外,在进行指针比较时,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)....

huge关键字:

huge指针,只有巨指针才是一般C语言教科书上所说的指针,它像远指针也占4个字节。与远指针的显著差别是:当增量或减量超过64K字节段边界时,巨指针会自动修正段基址的值。因此,巨指针不但可以寻址内存中的任一区域,而且所寻址的数据目标可以超过64K字节。例如:

char huge  *hp=(char huge *)0xb800ffff;
hp++;  //在指针加1后,hp将指向C800:0000。

但是,巨指针总是比较慢的,因为编译必须生成一小段程序对指针进行32位而不是16位的加减运算,此外,由于huge指针是规则化指针,每一个实际内存地址只一个 huge指针,所有在指针比较时不会产生错误。

based关键字:

based指针,像近指针一样,基指针只占两个字节,这两个字节是地址的偏移量。像远指针一样,基指针可以寻址内存中的任一区域。近指针的段地址隐含地取自程序的数据段,远指针的段地址取自指针本身,基指针的段地址取法以及基指针的许多技术和应用问题.

huge指针与far指针的区别:

huge指针是经过规范过的,可以直接比较大小。不过由于要处理后进行比较,所以运算速度较慢,far指针不能直接比较大小,但由于只比较偏移量,所以far指针的运算速度较快,可以根据需要选用

各类指针之间的转换:   
far指针可以强制转换为near   指针,做法很简单,抛掉段地址只 保留偏移量。near指针也可以转换为far指针,Turbo   C的做法是从相   应的段寄存器中取得段地址。   
far指针有时也需要转换为huge指针,以便对指针进行比较或做   
其它操作。一种方法是通过下面这样一个规则化函数:

void normalize(void  far **p)
{*p = (void far*)(((long)*p ^ 0xffff000f) +(((long)*p ^ 0x0000fff0) << 12));
}

far指针与near指针相关推荐

  1. C++ 笔记(14)— 指针(指针声明、取地址、取值、new/delete、NULL指针、指针运算、指针数组、数组指针、指针传递给函数、从函数返回指针)

    1. 声明指针 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址.就像其他变量或常量一样,您必须在使用指 针存储其他变量地址之前,对其进行声明. 指针变量声明的一般形式为: type * ...

  2. Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参

    1. 复合数据类型 Go 语言基本的复合数据类型有指针.数组.切片.字典.通道.结构和接口等.格式如下: * pointerType // 指针类型, [n]elementType // 数组类型, ...

  3. c++ char数组初始化_c专题指针数组与指针的关联

    ----在今天开始写文章之前,让我不由的想起高中里面学的一篇文章中一段话语,是荀子写的<劝学>:积土成山,风雨兴焉:积水成渊,蛟龙生焉:积善成德,而神明自得,圣心备焉.故不积跬步,无以至千 ...

  4. C指针9:指针数组(即数组中的每个元素都是指针)

    前边已经讲过数组指针,强调的是指针,意思就是该指针指向的是数组(数组里边的元素一般为普通数据). 指针数组,强调的是数组,意思就是该数组里边的每个元素都是指针类型.即如果一个数组中的所有元素保存的都是 ...

  5. C指针6:指针变量作为函数参数

    在C语言中,函数的参数不仅可以是整数.小数.字符等具体的数据,还可以是指向它们的指针.用指针变量作函数参数可以将函数外部的地址传递到函数内部,使得在函数内部可以操作函数外部的数据,并且这些数据不会随着 ...

  6. C语言中“野指针”、“悬空指针”是什么?

    目录 1."野指针"(wild pointer) 2."悬空指针"(dangling pointer) 1."野指针"(wild point ...

  7. 从变量地址到指针再到指针变量

    标题中的3个概念:变量地址.指针and指针变量是依次出现的,逐个确定就可以明晰到底什么是我们常说的指针(其实是指针变量) 首先,变量在本质上是一段存储空间,既然是存储空间,就必有地址,一般每个字节有一 ...

  8. 2020-09-25C++学习笔记引用2:二级指针形参与指针形参的使用方法和区别重难点,主看综合代码(1、指针形参2、引用形参3、二级指针形参4、指针引用形参)

    2020-09-25C++学习笔记引用2:二级指针形参与指针引用搭配做形参的使用方法区别重难点,注意事项主看综合代码(1.指针形参2.引用形参3.二级指针形参4.指针引用形参) 1.指针引用 #inc ...

  9. 深入理解指针以及二级指针(指针的指针)

    前言:本文将讲解指针的定义.指针变量和普通变量的本质区别.一级指针和二级指针的关系以及如何通过二级指针修改一级指针所指向的内存.文末还附加了两个实例,帮助读者加深对二级指针的理解.本文试图通过图表的方 ...

  10. 你必须知道的指针基础-3.指针的移动及指针的危险

    一.指针的移动 1.1 指针的向前及向后移动 指针每次加一就是指针向前移动指针类型对应的字节数.下面通过一个int指针来指向一个int数组,看看指针的加法运算到底是个什么鬼? int nums[]={ ...

最新文章

  1. 【408预推免复习】计算机组成原理之指令系统
  2. QRCode简介(收藏)
  3. C 语言实现数组冒泡排序
  4. python 测试mysql数据库_Python操作MySQL数据库----继续安装和测试
  5. 高频面试题2:单例设计模式
  6. 电脑怎么开护眼模式_心累!整天对着手机电脑,到底该怎么护眼啊啊啊
  7. 【Vue中的坑】Vue中的修改变量没有效果?
  8. C++ primer 5th 读完的一点心得体会
  9. P2P网贷行业的新征程
  10. 直播带货行业如何入局?先了解一下直播商城源码吧
  11. 百分点认知智能实验室出品:智能问答中的对抗攻击及防御策略
  12. ASEMI整流桥GBP406~GBP410,GBP406参数,GBP410图片
  13. 商用密码产品及对应规范介绍
  14. 雪花算法的基本理念和简单示例
  15. Python 求交错序列前N项和
  16. 对话雪球创始人方三文:「打工人」如何选行业、找工作、挑老板?|创新大会 2021...
  17. C语言 计算签到所得积分
  18. 客厅装修应注意空间的布局
  19. 斐讯盒子N1-docker入门二(制作openwrt)
  20. 【转】三种方法让你在I2C通信中同时和多个从机通信

热门文章

  1. 加快数字创新赋能实体经济 CDEC2021中国数字智能生态大会成都站今日举行
  2. 罗曼 matlab,成年人简易钢琴教程100首
  3. php教程数据库,php数据库基础
  4. 邮箱要钱吗?注册邮箱要钱吗?怎么申请注册邮箱?
  5. 邮政平邮批量查询未签收物流的方法
  6. H264H265格式
  7. mysql where 位子,mysql中 地里位置搜索 (抄)
  8. 原神如何修改服务器,原神PC端界面太大怎么修改 pc窗口界面调整方法分享[多图]...
  9. shader着色器基础课08-20
  10. 【STM32】HC-05蓝牙模块