✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/fYaBd
📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
28. extern 的作用
extern 可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外 extern 也可用来进行链接指定。
extern 有两个作用,第一,当它与 "C" 一起连用时,因为 C 和 C++ 生成符号的方式不同,C 和 C++ 语言之间的 API 接口是无法直接调用的,C 语言的函数声明必须扩在 extern "C"{} 中。
如:extern "C" void fun(int a, int b); 则告诉编译器在编译 fun 这个函数名时按着 C 的规则去翻译而不是 C++ 的,C++ 的规则在翻译这个函数名时会把 fun 这个名字变得面目全非。
因为,C++ 语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而 C 语言则不会,因此会造成链接时找不到对应函数的情况,此时 C 函数就需要用 extern "C" 进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
extern "C" 将 C++ 的 name mangling 机制关闭了,这样函数名就不会被 C++ 取的稀奇古怪,原来是什么样就是什么样。
需要注意的是, extern "C" 关键字只对函数的名称和调用约定起作用,对于函数的参数类型和返回值类型没有影响。
所以,在使用 extern "C" 声明函数时,需要保证函数的参数类型和返回值类型与 C 语言的定义相同,否则会导致编译错误或运行时错误.
总结:
-
extern "C" 只是 C++ 的关键字,不是 C 的。
-
被 extern "C" 修饰的目标一般是对一个全局 C 或者 C++ 函数的声明。
-
extern "C " 这个关键字声明的真实目的,就是实现 C++ 与 C 及其它语言的混合编程。
第二,当 extern 不与 "C" 在一起修饰变量或函数时,extern 用于指示变量或函数的定义在另一个源文件中,并在当前源文件中声明。说明该符号具有外部链接 (external linkage) 属性。
也就是告诉编译器:这个符号在别处定义了,你先编译,到时候链接器会去别的地方找这个符号定义的地址。
29. extern 的符号的声明与定义
首先明白 C/C++ 中变量的声明和定义是两个不同的概念声明是指告诉编译器某个符号的存在,在程序变量表中记录类型和名字,而定义则是指为该符号分配内存空间或实现其代码逻辑。
凡是没有带 extern 的声明同时也都是定义。
而对函数而言,带有 {} 是定义,否则是声明。如果想声明一个变量而非定义它,就在变量名前添加关键字 extern ,且不要显式的初始化变量。
// 声明
extern int global_var;
int sum(int a, int b);
// 定义
int global_var = 42;
int sum(int a, int b){
return a+b;
}
声明变量或函数的存在,但不进行定义,让编译器在链接时在其他源文件中查找定义这使得不同的源文件可以共享相同的变量或函数。
当链接器在一个全局变量声明前看到 extern 关键字,它会尝试在其他文件中寻找这个变量的定义。这里强调全局且非常量的原因是,全局非常量的变量默认是外部链接的。
30. 编译和链接的过程中,extern 的作用
编译链接过程中,extern 的作用如下:
-
在编译期 extern 用于告诉编译器某个变量或函数的定义在其他源文件中,编译器会为它生成一个符号表项,并在当前源文件中建立一个对该符号的引用。这个引用是一个未定义的符号,编译器在后续的链接过程中会在其他源文件中查找这个符号的定义。
-
在链接期,链接器将多个目标文件合并成一个可执行文件,并且在当前源文件中声明的符号,会在其它源文件中找到对应的定义,并将它们链接起来。
下面是一个使用 extern 声明全局变量的示例:
在上面的示例中, file1.cpp 文件中的 main 函数使用了全局变量 global_var ,但是 global_var 的定义是在 file2.cpp 中的,因此在 file1.cpp 中需要使用 extern 声明该变量。
在编译时,编译器会为 global_var 生成一个符号表项,并在 file1.cpp 中建立一个对该符号的引用。 的定义,并将其链接起来。在链接时,链接器会在其他源文件中查找 global_var。