C 函式名的修飾規則

2021-09-26 23:13:59 字數 1944 閱讀 8965

我們知道在c++中有函式過載這樣乙個東西,當我們定義了幾個功能類似且函式名是一樣的函式的時候,只要它的引數列表不同,編譯是可以通過的,但是在c中是不可以的。

double add(double a, double b)

int add(int a, char b)

char add(char a, char b)

如果這樣寫的**,在c中會報出errorc2371,說是add函式重定義。但是如果在c++環境下這樣是允許的,叫做函式的過載,只要你的幾個函式符合函式過載的要求,是完全沒有問題的。這就引出了在c和c++中函式名的修飾規則,為什麼在c 中就是不行的?

double add(double a, double b);

//我把這個函式的定義改為宣告,然後在main函式中呼叫,就可以看到提示中的

1. c編譯器的函式名修飾規則 

編譯器給我們報出了乙個鏈結錯誤,可以看到_add這樣的函式,這就是在c環境下編譯器對我們函式名的修飾,可以看到是在函式的前面加上下劃線,當然這種修改實在預設呼叫約定__cdecl的情況下,如果在__stdcall呼叫約定,編譯器和鏈結器會在輸出函式名前加上乙個下劃線字首,函式名後面加上乙個「@」符號和其引數的位元組數,__fastcall呼叫約定在輸出函式名前加上乙個「@」符號,後面也是乙個「@」符號和其引數的位元組數。

我們可以修改一下呼叫約定,看看是不是這樣的。

這樣修改之後再看看,可以看到add函式被修飾為_add@16.所以在不同呼叫約定下修飾規則也是有所不同的。

1. c++編譯器的函式名修飾規則 

然後,再看看在c++環境下,編譯器對我們的函式是怎樣修飾的:

可以看到,對於我宣告的double add(double a,double b)函式,被修飾為 (?add@@yannn@z),可以看到,這和在c環境中是完全不一樣的,所以這也是在c++中有函式過載的原因,那麼來看看這到底是怎麼修飾的。

c++的函式名修飾規則有些複雜,但是資訊更充分,通過分析修飾名不僅能夠知道函式的呼叫方式,返回值型別,引數個數甚至引數型別。不管__cdecl,__fastcall還是__stdcall呼叫方式,函式修飾都是以乙個「?」開始,後面緊跟函式的名字,再後面是參數列的開始標識和按照引數型別代號拼出的參數列。對於__stdcall方式,參數列的開始標識是「@@yg」,對於__cdecl方式則是「@@ya」,對於__fastcall方式則是「@@yi」。參數列的拼寫代號如下所示: 

x--void    

d--char    

e--unsigned char    

f--short    

h--int    

i--unsigned int    

j--long    

k--unsigned long(dword) 

m--float    

n--double    

_n--bool 

u--struct 

可以看到n是代表double型別,那麼 (?add@@yannn@z)就能理解了,函式修飾符?,接著是函式名字,然後是_cdecl約定的開始標示符@@ya然後連著的是返回值型別,引數列表的引數型別剛好是,那麼double add(double a,double b)就是nnn,參數列後以「@z」標識整個名字的結束,如果該函式無引數,則以「z」標識結束。

還有當引數列表有指標的時候,指標的方式有些特別,用pa表示指標,用pb表示const型別的指標。後面的代號表明指標型別,如果相同型別的指標連續出現,以「0」代替,乙個「0」代表一次重複。

舉乙個簡單的例子: int fun(int *p1, int *p2);

可以看到,我的fun函式被修飾為(?fun@@yahpah0@z)。

還有在c++中的成員函式中公有和私有的成員函式的修飾也有相應的表示符。總而言之,在c++環境中的函式名修飾的時候,會帶有引數列表的資訊,還有返回值的資訊,所以在c++中的函式過載就是允許存在的,因為它可以根據你的引數列表選擇對應的函式,而顯然在我們的c環境下是不允許的。

編譯器的函式名修飾規則

函式的名字修飾 decorated name 就是編譯器在編譯期間建立的乙個字串,用來指明函式的定義或原型。link程式或其他工具有時需要指定函式的名字修飾來定位函式的正確位置。多數情況下程式設計師並不需要知道函式的名字修飾,link程式或其他工具會自動區分他們。當然,在某些情況下需要指定函式的名字...

C和C 編譯器的函式名修飾規則

c編譯器的函式名修飾規則 對於 stdcall呼叫約定,編譯器和鏈結器會在輸出函式名前加上乙個下劃線字首,函式名後面加上乙個 符號和其引數的位元組數 例如 functionname number。cdecl呼叫約定僅在輸出函式名前加上乙個下劃線字首 例如 functionname。fastcall呼...

函式呼叫約定與函式名稱修飾規則 VC

inte2000 163.com 使用c c 語言開發軟體的程式設計師經常碰到這樣的問題 有時候是程式編譯沒有問題,但是鏈結的時候總是報告函式不存在 經典的lnk 2001錯誤 有時候是程式編譯和鏈結都沒有錯誤,但是只要呼叫庫中的函式就會出現堆疊異常。這些現象通常是出現在c和c 的 混合使用的情況下...