c++中的external function什么意思 unresolved external symbol 是什么...

c++\u4e2d\u7684extern\u4fee\u9970\u7b26\u5728\u53d8\u91cf\u7684 \u58f0\u660e\u548c\u5b9a\u4e49\u65b9\u9762\u6709\u4ec0\u4e48\u4f5c\u7528

\u5728C\u8bed\u8a00\u4e2d\uff0c\u4fee\u9970\u7b26extern\u7528\u5728\u53d8\u91cf\u6216\u8005\u51fd\u6570\u7684\u58f0\u660e\u524d\uff0c\u7528\u6765\u8bf4\u660e\u201c\u6b64\u53d8\u91cf/\u51fd\u6570\u662f\u5728\u522b\u5904\u5b9a\u4e49\u7684\uff0c\u8981\u5728\u6b64\u5904\u5f15\u7528\u201d\u3002


1. extern\u4fee\u9970\u53d8\u91cf\u7684\u58f0\u660e\u3002\u4e3e\u4f8b\u6765\u8bf4\uff0c\u5982\u679c\u6587\u4ef6a.c\u9700\u8981\u5f15\u7528b.c\u4e2d\u53d8\u91cfint v\uff0c\u5c31\u53ef\u4ee5\u5728a.c\u4e2d\u58f0\u660eextern int
v\uff0c\u7136\u540e\u5c31\u53ef\u4ee5\u5f15\u7528\u53d8\u91cfv\u3002\u8fd9\u91cc\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u88ab\u5f15\u7528\u7684\u53d8\u91cfv\u7684\u94fe\u63a5\u5c5e\u6027\u5fc5\u987b\u662f\u5916\u94fe\u63a5\uff08external\uff09\u7684\uff0c\u4e5f\u5c31\u662f\u8bf4a.c\u8981\u5f15\u7528\u5230v\uff0c\u4e0d\u53ea\u662f\u53d6\u51b3\u4e8e\u5728
a.c\u4e2d\u58f0\u660eextern int
v\uff0c\u8fd8\u53d6\u51b3\u4e8e\u53d8\u91cfv\u672c\u8eab\u662f\u80fd\u591f\u88ab\u5f15\u7528\u5230\u7684\u3002\u8fd9\u6d89\u53ca\u5230c\u8bed\u8a00\u7684\u53e6\u5916\u4e00\u4e2a\u8bdd\u9898\uff0d\uff0d\u53d8\u91cf\u7684\u4f5c\u7528\u57df\u3002\u80fd\u591f\u88ab\u5176\u4ed6\u6a21\u5757\u4ee5extern\u4fee\u9970\u7b26\u5f15\u7528\u5230\u7684\u53d8\u91cf\u901a\u5e38\u662f\u5168\u5c40\u53d8
\u91cf\u3002\u8fd8\u6709\u5f88\u91cd\u8981\u7684\u4e00\u70b9\u662f\uff0cextern int v\u53ef\u4ee5\u653e\u5728a.c\u4e2d\u7684\u4efb\u4f55\u5730\u65b9\uff0c\u6bd4\u5982\u4f60\u53ef\u4ee5\u5728a.c\u4e2d\u7684\u51fd\u6570fun\u5b9a\u4e49\u7684\u5f00\u5934\u5904\u58f0\u660eextern int

v\uff0c\u7136\u540e\u5c31\u53ef\u4ee5\u5f15\u7528\u5230\u53d8\u91cfv\u4e86\uff0c\u53ea\u4e0d\u8fc7\u8fd9\u6837\u53ea\u80fd\u5728\u51fd\u6570fun\u4f5c\u7528\u57df\u4e2d\u5f15\u7528v\u7f62\u4e86\uff0c\u8fd9\u8fd8\u662f\u53d8\u91cf\u4f5c\u7528\u57df\u7684\u95ee\u9898\u3002\u5bf9\u4e8e\u8fd9\u4e00\u70b9\u6765\u8bf4\uff0c\u5f88\u591a\u4eba\u4f7f\u7528\u7684\u65f6\u5019\u90fd\u5fc3\u5b58\u987e\u8651\u3002
\u597d\u50cfextern\u58f0\u660e\u53ea\u80fd\u7528\u4e8e\u6587\u4ef6\u4f5c\u7528\u57df\u4f3c\u7684\u3002


2.
extern\u4fee\u9970\u51fd\u6570\u58f0\u660e\u3002\u4ece\u672c\u8d28\u4e0a\u6765\u8bb2\uff0c\u53d8\u91cf\u548c\u51fd\u6570\u6ca1\u6709\u533a\u522b\u3002\u51fd\u6570\u540d\u662f\u6307\u5411\u51fd\u6570\u4e8c\u8fdb\u5236\u5757\u5f00\u5934\u5904\u7684\u6307\u9488\u3002\u5982\u679c\u6587\u4ef6a.c\u9700\u8981\u5f15\u7528b.c\u4e2d\u7684\u51fd\u6570\uff0c\u6bd4\u5982\u5728
b.c\u4e2d\u539f\u578b\u662fint fun(int mu)\uff0c\u90a3\u4e48\u5c31\u53ef\u4ee5\u5728a.c\u4e2d\u58f0\u660eextern int fun\uff08int
mu\uff09\uff0c\u7136\u540e\u5c31\u80fd\u4f7f\u7528fun\u6765\u505a\u4efb\u4f55\u4e8b\u60c5\u3002\u5c31\u50cf\u53d8\u91cf\u7684\u58f0\u660e\u4e00\u6837\uff0cextern int fun\uff08int
mu\uff09\u53ef\u4ee5\u653e\u5728a.c\u4e2d\u4efb\u4f55\u5730\u65b9\uff0c\u800c\u4e0d\u4e00\u5b9a\u975e\u8981\u653e\u5728a.c\u7684\u6587\u4ef6\u4f5c\u7528\u57df\u7684\u8303\u56f4\u4e2d\u3002\u5bf9\u5176\u4ed6\u6a21\u5757\u4e2d\u51fd\u6570\u7684\u5f15\u7528\uff0c\u6700\u5e38\u7528\u7684\u65b9\u6cd5\u662f\u5305\u542b\u8fd9\u4e9b\u51fd\u6570\u58f0\u660e\u7684\u5934\u6587\u4ef6\u3002\u4f7f\u7528
extern\u548c\u5305\u542b\u5934\u6587\u4ef6\u6765\u5f15\u7528\u51fd\u6570\u6709\u4ec0\u4e48\u533a\u522b\u5462\uff1fextern\u7684\u5f15\u7528\u65b9\u5f0f\u6bd4\u5305\u542b\u5934\u6587\u4ef6\u8981\u7b80\u6d01\u5f97\u591a\uff01extern\u7684\u4f7f\u7528\u65b9\u6cd5\u662f\u76f4\u63a5\u4e86\u5f53\u7684\uff0c\u60f3\u5f15\u7528\u54ea\u4e2a\u51fd\u6570
\u5c31\u7528extern\u58f0\u660e\u54ea\u4e2a\u51fd\u6570\u3002\u8fd9\u5927\u6982\u662fKISS\u539f\u5219\u7684\u4e00\u79cd\u4f53\u73b0\u5427\uff01\u8fd9\u6837\u505a\u7684\u4e00\u4e2a\u660e\u663e\u7684\u597d\u5904\u662f\uff0c\u4f1a\u52a0\u901f\u7a0b\u5e8f\u7684\u7f16\u8bd1\uff08\u786e\u5207\u7684\u8bf4\u662f\u9884\u5904\u7406\uff09\u7684\u8fc7\u7a0b\uff0c\u8282\u7701\u65f6\u95f4\u3002\u5728\u5927\u578bC\u7a0b\u5e8f\u7f16\u8bd1\u8fc7\u7a0b\u4e2d\uff0c\u8fd9\u79cd\u5dee\u5f02\u662f\u975e\u5e38\u660e\u663e\u7684\u3002


3. \u6b64\u5916\uff0cextern\u4fee\u9970\u7b26\u53ef\u7528\u4e8e\u6307\u793aC\u6216\u8005C\uff0b\uff0b\u51fd\u6570\u7684\u8c03\u7528\u89c4\u8303\u3002\u6bd4\u5982\u5728C\uff0b\uff0b\u4e2d\u8c03\u7528C\u5e93\u51fd\u6570\uff0c\u5c31\u9700\u8981\u5728C\uff0b\uff0b\u7a0b\u5e8f\u4e2d\u7528extern \u201cC\u201d\u58f0\u660e\u8981\u5f15\u7528\u7684\u51fd\u6570(\u53ea\u6709C++\u624d\u6709extern \u201cC\u201d\u7684\u7528\u6cd5\uff0c\u5728C\u4e2d\u8fd9\u6837\u7528\u4f1a\u62a5\u9519)\u3002\u8fd9\u662f\u7ed9\u94fe\u63a5\u5668\u7528\u7684\uff0c\u544a\u8bc9\u94fe\u63a5\u5668\u5728\u94fe\u63a5\u7684\u65f6\u5019\u7528C\u51fd\u6570\u89c4\u8303\u6765\u94fe\u63a5\u3002\u4e3b\u8981\u539f\u56e0\u662fC\uff0b\uff0b\u548cC\u7a0b\u5e8f\u7f16\u8bd1\u5b8c\u6210\u540e\u5728\u76ee\u6807\u4ee3\u7801\u4e2d\u547d\u540d\u89c4\u5219\u4e0d\u540c\u3002


4.\u5bf9\u4e8eextern\u53d8\u91cf\u6765\u8bf4\uff0c\u4ec5\u4ec5\u662f\u4e00\u4e2a\u53d8\u91cf\u7684\u58f0\u660e\uff0c\u5176\u5e76\u4e0d\u662f\u5728\u5b9a\u4e49\u5206\u914d\u5185\u5b58\u7a7a\u95f4\u3002\u5982\u679c\u8be5\u53d8\u91cf\u5b9a\u4e49\u591a\u6b21\uff0c\u4f1a\u6709\u8fde\u63a5\u9519\u8bef\u3002extern\u7528\u5728\u53d8\u91cf\u58f0\u660e\u4e2d\u5e38\u5e38\u6709\u8fd9\u6837\u4e00\u4e2a\u4f5c\u7528\uff0c\u4f60\u5728*.c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u4e86\u4e00\u4e2a\u5168\u5c40\u7684\u53d8\u91cf\uff0c\u8fd9\u4e2a\u5168\u5c40\u7684\u53d8\u91cf\u5982\u679c\u8981\u88ab\u5f15\u7528\uff0c\u5c31\u653e\u5728*.h\u4e2d\u5e76\u7528extern\u6765\u58f0\u660e\u3002


5.extern\u662fC/C++\u8bed\u8a00\u4e2d\u8868\u660e\u51fd\u6570\u548c\u5168\u5c40\u53d8\u91cf\u4f5c\u7528\u8303\u56f4\uff08\u53ef\u89c1\u6027\uff09\u7684\u5173\u952e\u5b57\uff0c\u8be5\u5173\u952e\u5b57\u544a\u8bc9\u7f16\u8bd1\u5668\uff0c\u5176\u58f0\u660e\u7684\u51fd\u6570\u548c\u53d8\u91cf\u53ef\u4ee5\u5728\u672c\u6a21\u5757\u6216\u5176\u5b83\u6a21\u5757\u4e2d\u4f7f\u7528\u3002\u901a\u5e38\uff0c\u5728\u6a21\u5757\u7684\u5934\u6587\u4ef6\u4e2d\u5bf9\u672c\u6a21\u5757\u63d0\u4f9b\u7ed9\u5176\u5b83\u6a21\u5757\u5f15\u7528\u7684\u51fd\u6570\u548c\u5168\u5c40\u53d8\u91cf\u4ee5\u5173\u952e\u5b57extern\u58f0\u660e\u3002\u4e5f\u5c31\u662f\u8bf4c\u6587\u4ef6\u91cc\u9762\u5b9a\u4e49\u51fd\u6570\u548c\u53d8\u91cf\uff0c\u5982\u679c\u8be5\u51fd\u6570\u6216\u8005\u53d8\u91cf\u6b32\u5f00\u653e\u7ed9\u5916\u90e8\u6587\u4ef6\uff0c\u5219\u5728h\u6587\u4ef6\u4e2d\u7528extern\u52a0\u4ee5\u58f0\u660e\u3002\u5219\u5916\u90e8\u6587\u4ef6\u53ea\u9700include\u8be5h\u6587\u4ef6\u5c31\u53ef\u4ee5\u4e86\u3002\u800c\u4e14\u7f16\u8bd1\u9636\u6bb5\uff0c\u5916\u90e8\u6587\u4ef6\u662f\u627e\u4e0d\u5230\u8be5\u51fd\u6570\u6216\u8005\u53d8\u91cf\u7684\uff0c\u4f46\u662f\u4e0d\u62a5\u9519\u3002link\u9636\u6bb5\u4f1a\u4ece\u539f\u5148\u6a21\u5757\u751f\u6210\u7684\u76ee\u6807\u4ee3\u7801\u4e2d\u627e\u5230\u6b64\u51fd\u6570\u548c\u53d8\u91cf\u3002


6.\u51fd\u6570\u7684\u58f0\u660e\u9ed8\u8ba4\u662fextern\u7684\uff0c\u5982\u679c\u51fd\u6570\u7684\u58f0\u660e\u4e2d\u5e26\u6709\u5173\u952e\u5b57extern\uff0c\u4ec5\u4ec5\u662f\u6697\u793a\u8fd9\u4e2a\u51fd\u6570\u53ef\u80fd\u5728\u522b\u7684\u6e90\u6587\u4ef6\u91cc\u5b9a\u4e49\uff0c\u6ca1\u6709\u5176\u5b83\u4f5c\u7528\u3002\u5373\u4e0b\u8ff0\u4e24\u4e2a\u51fd\u6570\u58f0\u660e\u6ca1\u6709\u660e\u663e\u533a\u522b\uff1a

extern int f(); \u548cint f(); \u5f53\u7136\uff0c\u8fd9\u6837\u7684\u7528\u5904\u8fd8\u662f\u6709\u7684\uff0c\u5c31\u662f\u5728\u7a0b\u5e8f\u4e2d\u53d6\u4ee3include \u201c*.h\u201d\u6765\u58f0\u660e\u51fd\u6570\uff0c\u5728\u4e00\u4e9b\u590d\u6742\u7684\u9879\u76ee\u4e2d\uff0c\u5728\u6240\u6709\u7684\u51fd\u6570\u58f0\u660e\u524d\u6dfb\u52a0extern\u4fee\u9970\u662f\u4e00\u79cd\u6bd4\u8f83\u597d\u7684\u4e60\u60ef\u3002

\u5982\u679c\u5b9a\u4e49\u51fd\u6570\u7684c/cpp\u6587\u4ef6\u5728\u5bf9\u5e94\u7684\u5934\u6587\u4ef6\u4e2d\u58f0\u660e\u4e86\u5b9a\u4e49\u7684\u51fd\u6570\uff0c\u90a3\u4e48\u5728\u5176\u4ed6c/cpp\u6587\u4ef6\u4e2d\u8981\u4f7f\u7528\u8fd9\u4e9b\u51fd\u6570\uff0c\u53ea\u9700\u8981\u5305\u542b\u8fd9\u4e2a\u5934\u6587\u4ef6\u5373\u53ef\u3002

\u5982\u679c\u4f60\u4e0d\u60f3\u5305\u542b\u5934\u6587\u4ef6\uff0c\u90a3\u4e48\u5728c/cpp\u4e2d\u58f0\u660e\u8be5\u51fd\u6570\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u58f0\u660e\u5b9a\u4e49\u5728\u672c\u6587\u4ef6\u7684\u51fd\u6570\u4e0d\u7528\u201cextern\u201d\uff0c\u58f0\u660e\u5b9a\u4e49\u5728\u5176\u4ed6\u6587\u4ef6\u4e2d\u7684\u51fd\u6570\u7528
\u201cextern\u201d\uff0c\u8fd9\u6837\u5728\u672c\u6587\u4ef6\u4e2d\u8c03\u7528\u522b\u7684\u6587\u4ef6\u5b9a\u4e49\u7684\u51fd\u6570\u65f6\u5c31\u4e0d\u7528\u5305\u542b\u5934\u6587\u4ef6 include \u201c*.h\u201d\u6765\u58f0\u660e\u51fd\u6570\uff0c\u58f0\u660e\u540e\u76f4\u63a5\u4f7f\u7528\u5373\u53ef\u3002


7.\u5982\u679c\u5728\u6a21\u5757A\u4e2d\u51fd\u6570\u58f0\u660e\u4e86foo(int x,int y)\u4e3aextern "C"\u7c7b\u578b\uff0c\u800c\u6a21\u5757B\u4e2d\u5305\u542b\u7684\u662fextern int foo( int x, int y ) \uff0c\u5219\u6a21\u5757B\u627e\u4e0d\u5230\u6a21\u5757A\u4e2d\u7684\u51fd\u6570\uff1b\u53cd\u4e4b\u4ea6\u7136\u3002

\u5c31\u662f\u8be5\u6807\u8bc6\u7b26\u6ca1\u6709\u5b9a\u4e49\u3002
main.obj : error LNK2019: \u65e0\u6cd5\u89e3\u6790\u7684\u5916\u90e8\u7b26\u53f7 "void __cdecl DeleteList(struct NODE * *,int)" (?DeleteList@@YAXPAPAUNODE@@H@Z)\uff0c\u8be5\u7b26\u53f7\u5728\u51fd\u6570 _main \u4e2d\u88ab\u5f15\u7528
main.obj : error LNK2019: \u65e0\u6cd5\u89e3\u6790\u7684\u5916\u90e8\u7b26\u53f7 "void __cdecl OutputList(struct NODE *)" (?OutputList@@YAXPAUNODE@@@Z)\uff0c\u8be5\u7b26\u53f7\u5728\u51fd\u6570 _main \u4e2d\u88ab\u5f15\u7528
main.obj : error LNK2019: \u65e0\u6cd5\u89e3\u6790\u7684\u5916\u90e8\u7b26\u53f7 "void __cdecl InsertList(struct NODE * *,int,int)" (?InsertList@@YAXPAPAUNODE@@HH@Z)\uff0c\u8be5\u7b26\u53f7\u5728\u51fd\u6570 _main \u4e2d\u88ab\u5f15\u7528
E:\Documents\Visual Studio 2005\Projects\formula\Debug\formula.exe : fatal error LNK1120: 3 \u4e2a\u65e0\u6cd5\u89e3\u6790\u7684\u5916\u90e8\u547d\u4ee4

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。

1. extern修饰变量的声明。举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2. extern修饰函数声明。从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

extern "C"的含义

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。
被extern "C"限定的函数或变量是extern类型的;
被extern "C"修饰的变量和函数是按照C语言方式编译和链接的

首先看看C++中对类似C的函数是怎样编译的。
作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。
_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。 例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

举例说明
(1)未加extern "C"声明时的连接方式
假设在C++中,模块A的头文件如下:
// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif
//在模块B中引用该函数:
// 模块B实现文件 moduleB.cpp
#include "moduleA.h"
foo(2,3);

实际上,在连接阶段,链接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

(2)加extern "C"声明后的编译和链接方式
加extern "C"声明后,模块A的头文件变为:
// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif

在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

<1>A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

<2>链接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo(int x, int y),则模块B找不到模块A中的函数;反之亦然。

extern “C”这个声明的真实目的是为了实现C++与C及其它语言的混合编程。

在C++中external function是外部函数的意思,而外部函数有两种理解.(1)库函数是C语言的内部函数或自带函数,外部函数即程序员自定函数.
(2)凡加写了extern 的函数是外部函数.

扩展阅读:c++中<< ... c++教程 ... c++编程器手机版下载 ... python和c++学哪个好 ... extern c++用法 ... c++编程 ... 手机c++编程软件 ... c++在线编译器官网 ... microsoft visual c++ ...

本站交流只代表网友个人观点,与本站立场无关
欢迎反馈与建议,请联系电邮
2024© 车视网