C++函數名稱修飾規律例解【之一】【原創qduwg】

C++函數名修飾編碼規則
-------------------------------
2010年8月19日qduwg原創

下面是總結的對C++名字修飾的一些規則,通過大量的實驗搞出的。其中需要在VC內寫一個小程序,然後通過單步調試,可以看出其編碼規則,也

可以使用cl /Fc /c xx.cpp方法編譯你的cpp文件,得到一個xx.COD文件,在那裏也可以看到修飾後的名字及彙編代碼等。當然不瞭解一點編碼

規則,是無法看懂那些類似火星人編碼的文字的。故廢寢忘食一個多星期,白天晚上的幹,才整理出來以下資料,也是自己心血的結晶。聊以拋

磚引玉。


com(int,int)
( 複數類構造函數

構造函數爲?0,跟作用域comp,結束標誌@@,函數訪問類型Q,一般函數A常函數用B,調用規則E(this)。參數爲2個整數,HH表示。@Z爲函數標誌

com com();
複數類構造函數,無參數。

構造函數爲?0,跟作用域comp,結束標誌@@,函數訪問類型Q,一般函數A常函數用B,調用規則E(this)。無參數用X表示。Z爲函數標誌,前面沒有那

個@號。

c1.add(c2); //c1,c2分別爲複數類對象
)複數類成員函數。
?成員函數名add,域名comp,結束標誌@@,QAE含義同前,返回值類型AAV1,引用本層類的對象,@分隔符,然後參數AAV1,也是引用本類對象,分

隔符@,函數結束標誌@Z。注意此時最後面的@@Z的兩個@之間沒有數字的。(see below,後面情況有變化)

增加一層名字空間時:
         // 如果自定義了名字空間wang,可以看出作用域的變化。

增加二層名字空間時:
函數原型comp& add(comp& a)
// 如果在自定義名字空間wang外層又定義了一個gang名字空間域,可以看出作用域的變化。

增加二層名字空間時:
函數原型comp& add(comp& a,comp& b)        //函數參數爲多個,且有重複前面的參數的時候。
//如果增加了多層名字空間,那麼在參數的後面就會出現相應的層號1,2,3等,而且在原來的@@Z

的兩個@之間增加一個數字0.表示重複前面第0號參數。 如果有不同類型參數,則填入相應代號即可,替換掉數字。參見後面實例描述。

cout<<i;

輸出整數變量i,函數?6表示<<符號,後跟所在範圍是@@,其中表示類型名

及包含的參數,DU分別表示字符類型char和類類型class,後面@@,爲第二個參數類類型的具體描述,其中@爲參數類型,

std@@爲char_traits類所在域,然後是外層類$basic_ostream的範圍std@@,然後是QAE,含義同前,接着是返回值類型,AAV是表示對一個對象的

引用,0和1分別表示所引用對象參數,0表示跟前面第0個相同,即@DU,1表示跟前面第1個相同即@D(注意序號從0開始算起)。然後是函數參數,

這裏是H表示輸出整數,最後是結束標誌@Z。
注:這裏的範圍不是名字空間,是指有不同類構成的函數簽名,跟前面的名字空間不同的。類模板名由$開頭,然後是模板參數。

cout<<'\n';
//調用的內聯函數
這個名字是沒有類名修飾的名字,屬於公有函數。開始是名字?6std@@,然後是YA,公有函數,調用約定A,返回值類型AAV表示對類引用(AA表示

引用,V表示類),後面是引用的類,由@@描述,其後緊跟的是參數表,其中@0是內聯函數標誌,@AAV10

表示與0號參數相同類型,@D表示字符類型參數,@Z表示函數。

char * p,cout<<*p;
//調用的內聯函數
const char * p,cout<<*p;
//調用的內聯函數

const unsigned char ch='a';const unsigned char * p=&ch;cout<<*p;
//@E是unsigned char

cout<<ch
//調用的內聯函數

cout<<f
      //調用的成員函數

cout<<db
      //調用的成員函數

cout<<ld
      //調用的成員函數

cout<<s
      //調用的成員函數

-------------------------------------------

在外層名字空間wang內定義了Time類,然後作爲參數傳遞給comp& add(comp&,Time&),返回comp&

QAE後的AAV1表示返回本類類型數據,第二個@AAV123表示參數類型也是對本類型的引用,@AAVTime@3對第三層名字空間內的Time進行引用作爲參

數。
層次關係可以看出從左往右排列,名字空間是從內層往外層的順序。@3表示域代號,在第三層。從內往外數。

inline comp& add(comp& a,Time& b)內聯函數

comp& add(comp& a,Time& b) 普通類外函數處於第二層名字空間

上面這兩個函數不管是不是inline都一樣的名字。編譯後代碼相同。但是名字跟前面的不同,因爲不屬於某個類的函數了。AAVcomp表示返回值類

型,@12表示在層號序列。@AAV312表示引用類型跟前面位於12層的相同。@AAVTime@2表示參數類型是對位於第二層上的Time的引用。所有層號都

是站在本函數的角度向外看出去時確定的層號。

------------------------------------------
在comp類內聲明內聯函數
inline comp& add(comp& a,Time& b),可以看到跟前面情況一樣的。也不屬於類成員。

函數定義爲三個參數時
inline comp& add(comp& a,Time& b,comp& c)

函數定義爲三個參數時
inline comp& add(Time& b,comp& a,comp& c)

函數定義爲三個相同的參數時
inline comp& add(comp& d,comp& a,comp& c)

註釋:可以看出,在非成員函數內,AAV3開頭的都是跟函數返回值類型有關的引用。
------------------------------------------

函數定義爲三個參數時且爲comp類的成員:
class comp& comp::add(comp& a,Time& b,comp& c)

class comp& comp::add(Time& b, comp& a,comp& c)

comp& add(comp& a,comp& c,Time& b);

作爲類成員函數的時候,參數表裏面參數的位置改變,編碼後的名字順序也改變。但是如果有重複的參數,後面參數只寫序號,而且是相對參數

表來說的,參數表第一個參數的序號爲0.
註釋:可以看出,在成員函數內,AAV1開頭的都是跟函數返回值類型有關的引用,而且都是本類類型的引用。
---------------------------------------
返回值爲Time類型時:
class Time& comp::add(comp& a,Time& b,comp& c);
//@AAV43中的@AAV4參考前面的3層上的類型。
返回值爲Time類型時:
class Time& comp::add(comp& a,comp& c,Time& b)
                ***
返回值爲Time類型時:
class Time& comp::add(Time& b, comp& a,comp& c)

返回值爲Time類型時:
class Time& comp::add( comp& a,Time& b,comp& c,Time& d)

註釋:可以看出,在成員函數內,AAV4開頭的都是跟函數返回值類型有關的引用。後面所跟數字即返回值類型所在層次路徑數字。
返回類型跟當前類不一致。
---------------------------------------------
返回值爲student類型時:參數爲4個。class student放在所有自定義名字空間之外。
class student& comp::add( comp& a,student& b,comp& c,student& d)


QAEAAVstudent@@最後的兩個@@之間沒有數字,說明前面那個返回值類型是全局類。

返回值爲student類型時:參數爲4個。放在gang名字空間內
            ***

返回值爲student類型時:參數爲4個。放在wang名字空間內。

註釋:可以看出,在成員函數內,AAV4開頭的都是跟函數返回值類型有關的引用。後面所跟數字即返回值類型所在層次路徑數字。
返回類型跟當前類不一致。

---------------------------------
student類放在wang名字空間,跟comp平行時:add函數不是類成員。放在類外了。
class student& add( comp& a,student& b,comp& c, student& d)
@AAVcomp@12 @AAV312 @01@Z         ***
student類放在wang名字空間,跟comp平行時:add函數不是類成員。放在類外了。五個參數,
class student& add( comp& a,student& b,comp& c, student& d,Time& t)

返回值是comp&類型:
class comp& add( comp& a,student& b,comp& c, student& d,Time& t)

返回值是Time&類型:

註釋:可以看出,在非成員函數內,AAV3開頭的都是跟函數返回值類型有關的引用。

-----------------------------------------------

返回值爲student類型時:參數爲4個。把student類放在comp類內,初始化時加上前綴域名,否則找不到。函數放在comp類外。
class comp::student& add( comp& a,comp::student& b,comp& c,comp::student& d)
@AAV412 @AAV3412 @01@Z //不是類成員函數了,前面沒有類名comp了。返回值類型帶。

@AAV412:412代表了comp,@AAV3412,表示參數類型student在comp內。

把student類放在time類內,作爲Public。引用student時必須寫上前綴Time:: 函數Add寫在comp類外的wang名字空間。
class Time& add( comp& a,Time::student& b,comp& c, Time::student& d,Time& t)


把student類放在time類內,作爲Public。返回值爲student類型時

在time類外又加了一層名字空間hongxia後,student類放在Time類內。
class hongxia::Time::student& add( comp& a,hongxia::Time::student& b,comp& c, hongxia::Time::student& d,hongxia::Time& t)

規律:總是以函數作爲起點向外看出去時,遇到的層數即名字空間嵌套層數爲1,2....,最外層號數最大,比如上述例子都是2,即gang名字空間

的代號。然後凡是返回值類型都從3編號,其所在類型號碼爲從內向外增加,比如student作爲返回值類型,則其代號爲3,所在外層類型依次加1

,如time類型爲4,然後如果外面還有一個層,則爲5,依次類推,然後是最外層號2.所有AAV的構成規律得到解決。

下面是又在最外層加了一層dong名字空間後的調用結果:

看出從add函數往外看出到最大層數是3,因此必然返回參數的編號從4開始。從返回類型層往外數到add函數的外一層,比如這裏是2,所以是Time

層數是5,外面的hongxia是6,然後是2層和3層。所以可以看出編碼規律AAV5623肯定是Time所在位置。而AAV45623一定是返回參數類型所在位置

了。這裏的4表示就是最大層數3以後的序號,一定從最大層數下一個開始作爲返回參數類型。然後後面就是所在類型的編號。

前面的域名後面的23表示從比add函數高一層的那個空間開始編號。也即2是add所在空間函數返回類型所在空間的共同的空間。說白了

就是要從共同所在層的層號開始寫出層序列。

=================================================================
上面這些規律是費了一週的時間,廢寢忘食通宵達旦的調試程序,查找資料,MSDN,網上的有關參考資料等,才整理出來的規律。希望對那些對

內部名字修飾(Name Mangling 或者Name Decoration)的朋友做一參考,也是拋磚引玉。畢竟這個問題也困擾了我好久好久。終於有一個名目了。

也是這一週多的時間的心血的結晶吧。

ps:參考小程序在另外一個頁面。

發佈了15 篇原創文章 · 獲贊 15 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章