天天看點

遠指針FAR/近指針NEAR/_STDCALL/_CDECL

今天看到inet_ntoa函數的原型,這個傳回類型實在是沒見過:

char FAR* PASCAL FAR inet_ntoa(struct in_addr in);

搜尋了一下:

1.關于FAR:(來自http://blog.csdn.net/sphone89/article/details/7184976)

FAR 是16位系統時候的概念了,代表遠指針的意思。

近指針是16位的指針,它隻表示段内的偏移位址,因而隻能對64k位元組資料段内位址進行存取。

  如 char near *p;

  p=(char near *)0xffff;

  遠指針是32位指針,它表示段位址:偏移位址,如定義遠端指針p指向B500段的2号位址,即B500:0002,則可寫作:

  char far *p;

  p=(char far *)0xB5000002;

  是以,遠指針可以進行跨段尋址,可以通路整個記憶體的位址。

     16位系統有遠近指針之分的環境中,得告訴編譯器指針變量h_name強制使用遠指針方式。因為16位系統尋址範圍隻有2^16=64K,是以用FAR指針,再加上16位,高16位存放的是變量的段位址,低16位存放變量的段内偏移。

2.關于PASCAL(來自http://bbs.csdn.net/topics/333630中的回複)

關于__stdcall和_cdecl

(提到PASCAL)

這兩個關鍵字看起來似乎很少和我們打交道,但是看了下面的定義(來自windef.h),你一定會覺得驚訝:

    #define CALLBACK    __stdcall

    #define WINAPI      __stdcall

    #define WINAPIV     __cdecl

    #define APIENTRY    WINAPI

    #define APIPRIVATE  __stdcall

    #define PASCAL      __stdcall

    #define cdecl _cdecl

    #ifndef CDECL

    #define CDECL _cdecl

    #endif

    幾乎我們寫的每一個WINDOWS API函數都是__stdcall類型的,為什麼??

    首先,我們談一下兩者之間的差別:

      WINDOWS的函數調用時需要用到棧(STACK,一種先入後出的存儲結構)。當函數調用完成後,棧需要清楚,這裡就是問題的關鍵,如何清除??

      如果我們的函數使用了_cdecl,那麼棧的清除工作是由調用者,用COM的術語來講就是客戶來完成的。這樣帶來了一個棘手的問題,不同的編譯器産生棧的方式不盡相同,那麼調用者能否正常的完成清除工作呢?答案是不能。

      如果使用__stdcall,上面的問題就解決了,函數自己解決清除工作。是以,在跨(開發)平台的調用中,我們都使用__stdcall(雖然有時是以WINAPI的樣子出現)。

      那麼為什麼還需要_cdecl呢?當我們遇到這樣的函數如fprintf()它的參數是可變的,不定長的,被調用者事先無法知道參數的長度,事後的清除工作也無法正常的進行,是以,這種情況我們隻能使用_cdecl。

      到這裡我們有一個結論,如果你的程式中沒有涉及可變參數,最好使用__stdcall關鍵字