#include <stdio.h>
#include <Windows.h>
double add(double a, double b);
int main()
{
add(1.0, 2.0);
system("pause");
return 0;
}
這段程式碼編譯可以通過,但是連結通過不了
報錯:
錯誤 2 error LNK2019: 無法解析的外部符號 _add,該符號在函數 _main 中被參照
#include <stdio.h>
#include <Windows.h>
int add(int a, int b);
int main()
{
add(1, 2);
system("pause");
return 0;
}
這段程式碼可以通過編譯階段,但是無法通過連結階段
報錯:
錯誤 2 error LNK2019: 無法解析的外部符號 _add,該符號在函數 _main 中被參照
由上述兩個相同功能但資料型別不同的add函數的報錯可以看出:add函數在編譯之後存在符號表中的名字都是_add,而main函數名字是_main
所以,
VS編譯器編譯C檔案時對於相同名字的函數並不做區分
,都是以
_函數名
來命名
#include <iostream>
using namespace std;
int add(int a, int b);
double add(double a, double b);
int main()
{
add(1.0, 2.0);
add(1, 2);
system("pause");
return 0;
}
這段程式碼可以通過編譯,但是不能通過連結
報錯:
error LNK2019: 無法解析的外部符號 「int __cdecl add(int,int)」 (?add@@YAHHH@Z),該符號在函數 _main 中被參照
error LNK2019: 無法解析的外部符號 「double __cdecl add(double,double)」 (?add@@YANNN@Z),該符號在函數 _main 中被參照
由報錯可以看出:自定義函數的函數名經過編譯之後,變成了另外一種表現形式,對於同名函數有區分度
命名規則:【?函數名@@YA返回值資料型別對應字母+形引資料型別對應字母@Z】
對應關係:
- int -> H
- double-> N
- float -> M
- char -> D
- void -> X
- bool -> _N
例如:
int add(int ,int ) -> ?add@@YAHHH@Z
double func(double,double) -> ?func@@YANNN@Z
由此可以看出gcc編譯c之後,自定義函數的函數名不變,對於同名函數沒有區分度。
由此可以看出g++編譯CPP檔案之後,自定義函數的函數名改變了,可以對同名函數進行區分。
命名規則:【_Z + 函數名字長度 + 函數名 + 形引資料型別首字母】
例如:
int add(int ,int ) -> _Z 3 add i i
int func(double ,double ,double) -> _Z 4 func d d d
總結:無論是Windows作業系統還是Linux作業系統,基於這些作業系統的主流編譯器都有一下特點:
結:無論是Windows作業系統還是Linux作業系統,基於這些作業系統的主流編譯器都有一下特點:
因此,至於是 命名規則 導致 C語言不支援函數過載而CPP支援函數過載 ,還是 C語言不支援函數過載而CPP支援函數過載 導致 命名規則如此,其因果關係就仁者見仁智者見智啦