c語言學習心得一:__stdcall、__cdcel和__fastcall三者的區別
趙加奎
__stdcall、__cdecl和__fastcall是三種函式呼叫協議,函式呼叫協議會影響函式引數的入棧方式、棧內資料的清除方式、編譯器函式名的修飾規則等。如下圖所示,可以在ide環境中設定所有函式預設的呼叫協議,還可以在函式定義時單獨設定本函式的呼叫協議。
呼叫協議常用場合
__stdcall:windows api預設的函式呼叫協議。
__cdecl:c/c++預設的函式呼叫協議。
__fastcall:適用於對效能要求較高的場合。
函式引數入棧方式
__stdcall:函式引數由右向左入棧。
__cdecl:函式引數由右向左入棧。
__fastcall:從左開始不大於4位元組的引數放入cpu的ecx和edx暫存器,其餘引數從右向左入棧。
問題一:__fastcall在暫存器中放入不大於4位元組的引數,故效能較高,適用於需要高效能的場合。
棧內資料清除方式
__stdcall:函式呼叫結束後由被呼叫函式清除棧內資料。
__cdecl:函式呼叫結束後由函式呼叫者清除棧內資料。
__fastcall:函式呼叫結束後由被呼叫函式清除棧內資料。
問題一:不同編譯器設定的棧結構不盡相同,跨開發平台時由函式呼叫者清除棧內資料不可行。
問題二:某些函式的引數是可變的,如printf函式,這樣的函式只能由函式呼叫者清除棧內資料。
問題三:由呼叫者清除棧內資料時,每次呼叫都包含清除棧內資料的**,故可執行檔案較大。
c語言編譯器函式名稱修飾規則
__stdcall:編譯後,函式名被修飾為「_functionname@number」。
__cdecl:編譯後,函式名被修飾為「_functionname」。
__fastcall:編譯後,函式名給修飾為「@functionname@nmuber」。
注:「functionname」為函式名,「number」為引數位元組數。
注:函式實現和函式定義時如果使用了不同的函式呼叫協議,則無法實現函式呼叫。
c++語言編譯器函式名稱修飾規則
__stdcall:編譯後,函式名被修飾為「?functionname@@yg******@z」。
__cdecl:編譯後,函式名被修飾為「?functionname@@ya******@z」。
__fastcall:編譯後,函式名被修飾為「?functionname@@yi******@z」。
注:「******」為函式返回值型別和引數型別表。
注:函式實現和函式定義時如果使用了不同的函式呼叫協議,則無法實現函式呼叫。
c語言和c++語言間如果不進行特殊處理,也無法實現函式的互相呼叫。
c語言學習心得
變數是程式可操作的儲存區的名稱。c中每個變數都有特定的型別,型別決定了變數儲存的大小和布局,該範圍內的值都可以儲存在記憶體中,運算子可應用於變數上。即告訴編譯器在何處建立變數的儲存,以及如何建立變數的儲存。變數定義指定乙個資料型別,幷包含了該型別的乙個或多個變數的列表。變數宣告向編譯器保證以指定的型...
C語言學習心得
區域性變數僅在包含它的最內的大括號內有效 for迴圈中定義的變數僅在for迴圈內有效!在main 中定義的變數,不能在被調函式中使用 除全域性變數 普通變數或指標變數間的賦值,非位址概念 不同的普通變數或不同的指標變數在記憶體中所分配的空間位址不同 兩者間傳遞的是內容 對普通變數而言 內容僅僅是具體...
c語言學習心得(3)
學習c語言已經一年多,對c也算得上半個入門者,期間也寫過一些自娛自樂的 其實個人認為無論學習什麼語言,最重要的是掌握習程式設計思想,然而c語言一種學習程式設計思想的基礎語言。所以,c語言的重要性不言而喻。一 課本 無論用的是什麼書,要學好c語言,把書上的每乙個例題 習題的 讀懂,這是學c最基本的要求...