near指针,far指针,huge指针

near指针和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或far,那么默认是near。所以far指针要显式指定。far指针工作起来要慢一些,因为每次访问一个far指针时,都要将数据段或程序段的数据交换出来。另外,far指针的运算也比较反常,例如上面讲到的far指针指向同一个地址,但是比较的结果却不相同。

什么时候使用far指针?

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

FAR指针是|段地址:偏移地址|的形式。HUGE指针也是|段地址:偏移地址|的形式。

因为可以有每个段都是64K的,可以寻址多个段,所以这种指针的寻址范围很大如果你的程序代码或者数据超过了64K就只能用FAR指针或HUGE指针来操作了。

它们二者也是有区别的!

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

一、近(near)指针

近指针是用于不超过64K   字节的单个数据段或码段。对于数据指针,在微、小和中编译模式下产生的数据指针是近指针,因为此时只有一个不超过64K   字节的数据段。对于码(即函数指针)指针,在微、小和紧凑编译模式下产生的码指针是近指针,因为此时只一个不超过64K字节的码段。本章将只讨论数据指针。近指针是16位指针,它只含有地址的偏移量部分。为了形成32位的完整地址,编译程序一般是反近指针与程序的数据段的段地址组合起来。因为在大部分情况下程序的数据段的段地址是装在DS寄存器内,因此一般没有必要装载这个寄存器。此外,当用汇编语言和C语言混合编程时,汇编语言总是假设DS含有数据目标的地址。虽然近指针占用空间最小,执行速度最快,但它有一个严格的限制,即只能64K字节以内的数据,且只能存取程序的数据段内的数据。如果在小模式下编译一个程序,而这个程序企图增量一个近指针使之超过第65536个字节,则这个近的指针就会复位到0。下面就是这样一个例子:

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

p++;

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

二、远(far)指针

远指针不是让编译程序把程序数据段地址作为指针的段地址部分,而是把指针的段地址与指针的偏移量直接存放在指针内。因此,远指针是由4   个字节构成。它可以指向内存中的任一目标,可以用于任一编译模式,尽管仅在紧凑、大和巨模式下远指针才是缺省的数据指针。因为远指针的段地址在指针内,熟悉80X86   汇编语言的人都知道,这意味着每次使用远指针时都需要重新装载段寄存器,这显然会降低速度。应该注意:尽管远指针可以寻址内存中的任一单元,但它所寻址的目标也不能超过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)....

三、巨(huge)指针  

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

例如:  

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

hp++;  

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

此外,由于huge指针是规则化指针,每一个实际内存地址只一个huge指针,所有在指针比较时不会产生错误。

四、基(based)指针  

前面已经说过,巨指针综合了近指针和远指针的优点。像近指针一样,基指针只占两个字节,这两个字节是地址的偏移量。像远指针一样,基指针可以寻址内存中的任一区域。近指针的段地址隐含地取自程序的数据段,远指针的段地址取自指针本身,基指针的段地址取法以及基指针的许多技术和应用问题。  

五、各类指针之间的转换  

far指针可以强制转换为near   指针,做法很简单,抛掉段地址只保留偏移量。near指针也可以转换为far指针,Turbo C的做法是从相应的段寄存器中取得段地址。far指针有时也需要转换为huge指针,以便对指针进行比较或做其它操作。

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

void   normalize(void   far   **p)  

{  

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

时间: 2024-08-07 18:35:22

near指针,far指针,huge指针的相关文章

C++指针探讨(一)数据指针

指针,在C/C++语言中一直是很受宠的:几乎找不到一个不使用指针的C/C++应用.用于存储数据和程序的地址,这是指针的基本功能.用于指向整型数,用整数指针(int*):指向浮点数用浮点数指针(float*):指向结构,用对应的结构指针(struct xxx *):指向任意地址,用无类型指针(void*). 有时候,我们需要一些通用的指针.在C语言当中,(void*) 可以代表一切:但是在C++中,我们还有一些比较特殊的指针,无法用(void*)来表示.事实上,在C++中,想找到一个通用的指针,特

C/C++中字符指针数组及指向指针的指针的含义

就指向指针的指针,很早以前在说指针的时候说过,但后来发现很多人还是比较难以理解,这一次我们再次仔细说一说指向指针的指针. 先看下面的代码,注意看代码中的注解: #include <iostream>#include <string>using namespace std; void print_char(char* array[],int len);//函数原形声明void main(void){//-----------------------------段1----------

C# 指针学习笔记之指针类型

大学的时候学过C++.C,最近工作也不是很忙,就想起看看C#中的指针,看看.回忆一下啊,指针的用法,以下学习笔记摘自msdn:指针类型 在不安全的上下文中,类型可以是指针类型以及值类型或引用类型.指针类型声明具有下列形式之一: type* identifier; void* identifier; //allowed but not recommended 下列类型都可以是指针类型: sbyte.byte.short.ushort.int.uint.long.ulong.char.float.d

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言 ⁄ 评论数 3 ⁄ 被围观 1,775 views+   指针数组: 在一个数组中,如果它的元素全部都是指针

C++中的指针、数组指针与指针数组、函数指针与指针函数

C++中的指针.数组指针与指针数组.函数指针与指针函数 本文从初学者的角度,深入浅出地详解什么是指针.如何使用指针.如何定义指针.如何定义数组指针和函数指针,并给出对应的实例演示:接着,区别了数组指针与指针数组.函数指针与指针函数:最后,对最常混淆的引用传递.值传递和指针传递做了区处. C++中一个重要的特性就是指针,指针不仅具有获得地址的能力,还具有操作地址的能力.指针可以用于数组.或作为函数的参数,用来访问内存和对内存的操作,指针的使用使得C++很高效,但是指针也非常危险,使用不当会带来比较

c语言-c小白求教指针问题(定义指针变量的位置)

问题描述 c小白求教指针问题(定义指针变量的位置) 请教问什么1和2都可以编译通过,但是写到3的位置报错呢 #include <stdio.h> int main(){ int a = 10; int b = 100; int c = 1; // 1.int *d = &c; int *point_1,*point_2; //2. int *d = &c; point_1 = &a; point_2 = &b; //3.int *d = &c; prin

指针函数与函数指针

一. 在学习arm过程中发现这"指针函数"与"函数指针"容易搞错,所以今天,我自己想一次把它搞清楚,找了一些资料,首先它们之间的定义: 1.指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针      类型标识符    *函数名(参数表)       int *f(x,y);   首先它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋

关于指针数组和数组指针的区别

问题描述 关于指针数组和数组指针的区别 为什么上面那个就代表指针数组下面的就代表数组指针了呢 解决方案 指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针.和普通的变量定义一样,如果是要数组,变量名就是:a[4],数组存储的类型就是:int* 例如int* a[4] 数组指针:a pointer to an array,即指向数组的指针,和普通变量一样的定义,表示指针变量名 *a:指针int[]类型,int 以上是个人理解,如果有错误还请指正 解决方案二:

指针常量和常量指针

这2个概念非常容易混淆,即使是老鸟,也有眩晕的时候,写此博文,加深记忆...   指针常量:一个指针,并且它是一个常量,它的值不许被改变: char *const p1 = "Hello!"; //必须在定义的时候初始化,因为它是常量 p1 = "NiHao!"; //错误,不允许对常量赋值   常量指针:一个指针,并且它指向对象是一个常量(不许改变),但该指针本身的值可以被改变: const char *p2 = "Hello!"; //可以不