分類:DOSnear指標和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指標指向同一個地址,但是比較的結果卻不相同。
9、什麼時候使用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)指標
前面已經說過,巨指標綜合了近指標和遠指標的優點。像近指標
一樣,基指標只佔兩個位元組,這兩個位元組是地址的位移量。像遠指標
一樣,基指標可以定址記憶體中的任一地區。近指標的段地址隱含地取
自程式的資料區段,遠指標的段地址取自指標本身,基指標的段地址取
法以及基指標的許多技術和應用問題,請見第11章。
五、各類指標之間的轉換
far指標可以強制轉換為near 指標,做法很簡單,拋掉段地址只
保留位移量。near指標也可以轉換為far指標,Turbo C的做法是從相
應的段寄存器中取得段地址。
far指標有時也需要轉換為huge 指標,以便對指標進行比較或做
其它操作。一種方法是通過下面這樣一個規則化函數: void normalize(void far **p) {
*p=(void far *)(((long)*p^0xffff000f)+
(((long)*p^0x0000fff0)<<12));
}
你可以通過這個連結引用該篇文章:http://xpddk.bokee.com/tb.b?diaryId=17907924