對於C++編譯器命名粉碎規則(name mangling)機制的實驗

編譯器版本

在這裏插入圖片描述

測試案例

#include <iostream>
#include <string>

using std::string;
using std::cout;
using std::endl;


void print(int a) //_Z5printi
{

}

double print(double,double,int,int) //_Z5printddii
{
        return 0;
}

int print(int , int ,double,bool,char,short) //_Z5printiidbcs
{
        return 0;
}
string print(string, int, int, string) //_Z5printNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiiS4_
{
        return string();
}


int main()
{

        return 0;
}

查看編譯之後函數符號變化

在這裏插入圖片描述

結論

C++函數重載機制其實是編譯器後面所做的name mangling,實際上所有的函數名字符號都不一樣,否則必定二義性(彙編中符號可以看做一個地址,如果不同作用的函數共用一個符合那麼只能說明這2個函數必然完全等同就是同一個)。並且我們也能夠從中窺探一番編譯器是如何對函數進行命名的,即:

_xx + 函數名稱 + 參數類型

並且我們可以得知如果是內置類型通常爲類型的首字母。如果是類,以標準庫string類爲例子,那麼會明確的指明到的是哪個具體的類,因爲標準庫中string的實現是十分複雜的,最終是指向一個名爲basic_string的類,因此後面那一大串的東西其實用於指明是string的最終依賴。並且函數命名與函數返回值毫無關係。

產生的問題

最明顯的就是C和C++混合編程時可能導致未定義的問題,因爲C函數編譯後的符號命名並不遵循C++編譯器的玩法,使用直接使用C函數會導致些問題。因此問了解決C函數在C與C++編譯器之間的共通需要如下聲明C函數:

#ifdef __cplusplus
extern "C"
{
#endif //__cplusplus

//C函數聲明或者定義

#ifdef __cplusplus
}
#endif //__cplusplus

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章