C/C++中的近指令、远指针和巨指针
宋宝华 email:21cnbao@21cn.com sweek
在我们的C/C++学习生涯中、在我们大脑的印象里,通常只有指针的概念,很少听说指针还有远、近、巨之分的,从没听说过什么近指针、远指针和巨指针飞鸽传书
可以,某年某月的某一天,你突然看到这样的语句:
char near *p; /*定义一个字符型“近”指针*/
char far *p; /*定义一个字符型“远”指针*/
char huge *p; /*定义一个字符型“巨”指针*/
实在不知道语句中的“near”、“far”、“huge”是从哪里冒出来的,是个什么概念!本文试图对此进行解答,解除许多人的困惑。
这一点首先要从8086处理器体系结构和汇编渊源讲起。大家知道,8086是一个16位处理器,它设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。8086采用段式访问,访问本段(64K范围内)的数据或指令时,不需要变更段地址(意味着段地址寄存器不需修改),而访问本段范围以外的数据或指令时,则需要变更段地址(意味着段地址寄存器需要修改)。
因此,在16位处理器环境下,如果访问本段内地址的值,用一个16位的指针(表示段内偏移)就可以访问到;而要访问本段以外地址的值,则需要用16位的段内偏移+16位的段地址,总共32位的指针。
这样,我们就知道了远、近指针的区别:
Ø近指针是只能访问本段、只包含本段偏移的、位宽为16位的指针;
Ø远指针是能访问非本段、包含段偏移和段地址的、位宽为32位的指针。
近指针只能对64k字节数据段内的地址进行存取,如:
char near *p;
p=(char near *)0xffff;
远指针是32位指针,它表示段地址:偏移地址,远指针可以进行跨段寻址,可以访问整个内存的地址。如定义远程指针p指向0x1000段的0x2号地址,即1000:0002,则可写作:
char far *p;
p=(char far *)0x10000002;
除了远指针和近指针外,还有一个巨指针的概念。
和远指针一样,巨指针也是32位的指针,指针也表示为16位段:16位偏移,也可以寻址任何地址。它和远指针的区别在于进行了规格化处理。远指针没有规格化,可能存在两个远指针实际指向同一个物理地址,但是它们的段地址和偏移地址不一样,如23B0:0004和23A1:00F4都指向同一个物理地址23604!巨指针通过特定的例程保证:每次操作完成后其偏移量均小于10h,即只有最低4位有数值,其余数值都被进位到段地址上去了,这样就可以避免Far指针在64K边界时出乎意料的回绕的行为。当然,一次操作必须小于64K。下面的函数可以将远指针转换为巨指针:
void normalize(void far ** p)
{
  *p=(void far *)(((long)*p&0xffff000f)+(((long)*p&0x0000fff00<<12));
}
从上面的函数中我们再一次看到了指针之指针的使用,这个函数要修改指针的值,因此必须传给它的指针的指针作为参数。
讲到这里,笔者要强调的是:近指针、远指针、巨指针是段寻址的16bit处理器的产物(如果处理器是16位的,但是不采用段寻址的话,也不存在近指针、远指针、巨指针的概念),当前普通PC所使用的32bit处理器(80386以上)一般运行在保护模式下的,指针都是32位的,可平滑地址,已经不分远、近指针了。但是在嵌入式系统领域下,8086的处理器仍然有比较广泛的市场,如AMD公司的AM186ED、AM186ER等处理器,开发这些系统的程序时,我们还是有必要弄清楚指针的寻址范围。

如果读者还想更透彻地理解本文讲解的内容,不妨再温习一下微机原理、 8086 汇编,并参考 C/C++ 高级编程书籍的相关内容。

C/C++中的近指令、远指针和巨指针相关推荐

  1. 近指针, 远指针和巨指针

    近指针, 远指针和巨指针是在段寻址的16位处理器中产生的. (http://blog.csdn.net/zhoudengqing/article/details/41347607) 转载于:https ...

  2. 远指针,近指针,巨指针

    预备知识: 这与CPU寻址有关.在16位机器下,地址线为20位.但CPU处理能力只有16位.于是访问内存的方案是分段.即基址(段)+偏址是逻辑地址,从中可计算物理地址.基址(段)有16位,偏址也16位 ...

  3. dosbox中的bebug指令

    ( 1 )G命令 运行当前在内存中的程序. -g [=address] [breakpoints] 参数 =address 指定当前在内存中要开始执行的程序地址.如果不指定 address,Windo ...

  4. ARM中的---汇编指令

    ARM中的---汇编指令 一. 带点的(一般都是ARM GNU伪汇编指令) 1. ".text".".data".".bss" 依次表示的是 ...

  5. C++中内存分配方式、空指针及野指针的区别

    一.C++中内存分配方式可以分为三种: (1)从静态存储区域分配: 内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...

  6. 如何按距离排序 php,php做附近的人,根据距离由近到远进行排序

    用户登陆的时候会获取到该用户的经纬度,数据库中存有所有用户的经纬度,如何进行由近到远进行排序,并算出距离 可以考虑用GeoHASH实现,效率更高,参考这篇http://www.cnblogs.com/ ...

  7. 数据分析中,文本分析远比数值型分析重要!(上)

    温馨提示:本文是<数据分析中,文本分析远比数值型分析重要!>的上篇,聊的是文本分析的一些基本知识,下篇将以一个实际案例来聊聊基于大数据的文本分析是如何应用在商业场景中的,将于明天推送,敬请 ...

  8. 2021高考成绩查询镇远一中,离太阳由近到远的八大行星排序及记忆方法

    八大行星按照离太阳的距离从近到远,它们依次为水星.金星.地球.火星.木星.土星.天王星.海王星. 更多高考资讯尽在30高考网https://www.30gk.com/ 八大行星的排序 1.水星:在太阳 ...

  9. HTAP数据库 PostgreSQL 场景与性能测试之 6 - (OLTP) 空间应用 - KNN查询(搜索附近对象,由近到远排序输出)...

    标签 PostgreSQL , HTAP , OLTP , OLAP , 场景与性能测试 背景 PostgreSQL是一个历史悠久的数据库,历史可以追溯到1973年,最早由2014计算机图灵奖得主,关 ...

最新文章

  1. winform 弹出窗体位置设定
  2. ZOJ3715 竞选班长求最小花费
  3. 完全二叉树最小深度_二叉树:我有多少个节点?
  4. 如何将页脚固定在页面底部
  5. WebSnapshotsHelper(HTML转换为图片)
  6. java mediainfo.dll_MediaInfo库的简单使用
  7. angular input 为file on-change 无效
  8. hdu 4351 Digital root
  9. python参考手册下载_python学习手册下载|
  10. 同义词转换不再有效_1秒变电脑,手机吃鸡新体验,北通E1键鼠转换器上手体验!...
  11. 华为鸿蒙系统操作教程_华为鸿蒙DevEco studio2.0的安装和hello world运行教程
  12. 交换游戏(记忆化搜索,状态压缩,位运算)
  13. Arduino基础与常用函数
  14. The Fewest Coins (混合背包)
  15. 睿智的目标检测12——使用labelimg进行目标检测数据集标注
  16. Defcon - 2015 - 初赛 - r0pbaby writeup
  17. android 截取验证码的两种实现方式
  18. 冷门游戏脚本开发软件-TC
  19. ng2 绑定输出html,Angular2的数据绑定
  20. 【01】什么是 APP?移动 APP 有几种类型?

热门文章

  1. 如何梳理产品功能,才能既见森林又见树木?
  2. B端页面——详细表单设计流程
  3. 支付系统设计:支付系统的账户模型(一)
  4. B端可视化: 图表设计(2)
  5. 2020-2021年中国购物中心消费者洞察报告
  6. 2021公益数字化研究报告
  7. 抖音python课程价格_抖音
  8. 一种情感判别分析体系在汽车品牌舆情管理中的应用
  9. 作者:熊贇(1980-),女,博士,复旦大学计算机科学技术学院教授
  10. 【离散数学】幂集的求解