學(xué)過C/C++語言的都知道程序的執(zhí)行從main函數(shù)開始(先不說static對(duì)象和CRT),大部分學(xué)過C/C++的也都知道m(xù)ain可以有int main()和int main(int argc, char**argv)的參數(shù)格式,有不少人還知道int main(int, char**, char**)的參數(shù)形式,返回值也可以為void,但是為什么C/C++ compiler能夠支持這些格式呢?在初學(xué)C的時(shí)候,我以為是編譯器內(nèi)置的功能來支持
近日研究VC的CRT,發(fā)現(xiàn)原來是通過調(diào)用規(guī)范(calling coventions)實(shí)現(xiàn)的。
調(diào)用規(guī)范分為參數(shù)傳遞次序,調(diào)用棧維護(hù),命名修飾和大小寫轉(zhuǎn)換4個(gè)規(guī)范組成。
大部分的C語言編譯器(至少是在x86架構(gòu)上)遵循以下的規(guī)范
命名修飾和大小寫轉(zhuǎn)換:無論函數(shù)的signature是什么樣子,在編譯時(shí)會(huì)將名為“Xxxx”的函數(shù)轉(zhuǎn)換為“_Xxxx”的形式,即在函數(shù)名前面加上“_”,大小寫不變,也就是說不管是什么形式的main函數(shù),有沒有返回值,有多少個(gè)參數(shù)都會(huì)在編譯時(shí)轉(zhuǎn)換為_main。因此雖然在CRT中使用的是
int?__cdecl main(int,?char?**,?char?**);的形式聲明的main函數(shù),但是在鏈接的時(shí)候無論是什么形式的main都符合要求,只不過除了在文章開始提到的3種形式有意義外,其他的參數(shù)格式要么是得到無意義的值,要么還會(huì)溢出調(diào)用棧(使用超過3個(gè)參數(shù))
測(cè)試代碼如下:
int?main(int?a1,?char*?a2,?unsigned?long?a3,?float?a4,?double?a5,?unsinged?int?a6)
{
?printf("Hello?World!\n");
?return?0;
}
?