首先簡單說明兩點:
1. 編譯器編譯的基本單位是一個C文件或Cpp文件,並不對頭文件進行編譯。
2. extern “C”只能被C++編譯器處理,C編譯器並不認識這個標志。
還是使用上次分享的那篇文章中的示例代碼,代碼如下:
/*CppHeader.h*/
#ifndef CPP_HEADER
#define CPP_HEADER
extern "C" void print(int i);
#endif CPP_HEADER
/*CppHeader.cpp*/
#include "cppHeader.h"
#include <stdio.h>
#include <iostream.h>
void print(int i)
{
printf("cppHeader %d\n",i);
}
/*c.c*/
extern void print(int i);
int main(int argc,char** argv)
{
print(3);
return 0;
}
還是有3個文件:CppHeader.h,CppHeader.cpp和c.c。使用下面的命令手工那個手工進行編譯和鏈接:
cl /c /Tp CppHeader.cpp
cl /c /Tc c.c
link c.obj CppHeader.obj
會生成c.exe文件,而且運行正常。
現在,我們把CppHeader.cpp中的#include “cppHeader.h”去掉。再進行編譯,還是同樣的命令,就發現不會生成c.exe文件了。提示的錯誤為:
c.obj : error LNK2001: unresolved external symbol _print
c.exe : fatal error LNK1120: 1 unresolved externals
前後比較一下,我們發現只要在CppHeader.cpp文件中加入一句extern “C”void print(int i) ,程序就能夠正常編譯鏈接了。extern “C” 告訴C++編譯器,你把print()函數按照C的方式來編譯吧。這樣,C++編譯器就把print(int i)這個函數編譯為_print符號了,使用dumpbin工具可以看出來。
小小總結一些extern “C”的作用:
在某個C++源文件中,如果有extern “C”語句,那很可能有兩種情況:
1.被extern “C”修飾的函數在本文件中實現,那麼C++編譯器就把這個函數按照C的方式來進行編譯,本文件中別的函數調用此函數時按照C的方式來調用,或者說,按照C的方式鏈接。
2.被extern “C”修飾的函數在其它文件中實現,那麼本文件中的函數調用此函數,就按照C的方式來調用,或者說,按照C的方式鏈接。
摘自 canmeng50401的專欄