面试模拟场景
面试官: 你能解释一下extern关键字的作用吗?另外,extern变量存储在哪个数据段,以及为什么要使用extern "C"?
参考回答示例
1. extern 关键字的作用
1.1 extern 声明外部变量
-
作用:
extern用于声明一个变量或函数是在其他文件中定义的,告诉编译器该变量或函数在另一个编译单元(通常是另一个源文件)中已定义,而不是在当前文件中定义。- 这种机制允许不同的源文件共享同一个全局变量或函数。
-
示例:
// file1.cpp int count = 10; // 定义一个全局变量 // file2.cpp extern int count; // 声明这个变量在其他文件中定义 void func() { std::cout << count << std::endl; // 正确访问全局变量 count }- 解释: 在
file2.cpp中,使用extern int count;声明count变量,这表明count是在其他文件中定义的,而不是在当前文件中重新定义。
- 解释: 在
1.2 extern 声明外部函数
-
作用:
- 类似于变量,
extern也可以用于声明一个函数是在其他文件中定义的。这样可以在当前文件中调用该函数,而不需要在当前文件中定义它。
- 类似于变量,
-
示例:
// file1.cpp void printMessage() { std::cout << "Hello, World!" << std::endl; } // file2.cpp extern void printMessage(); // 声明外部函数 void func() { printMessage(); // 调用在其他文件中定义的函数 }- 解释: 在
file2.cpp中,通过extern void printMessage();声明printMessage函数,使得func函数可以调用在file1.cpp中定义的printMessage函数。
- 解释: 在
1.3 默认的extern行为
- 作用:
- 全局变量和函数在不加
extern关键字的情况下,默认是具有extern属性的,即可以被其他文件引用。不过在明确要共享全局变量或函数时,显式使用extern有助于代码的可读性和维护性。
- 全局变量和函数在不加
2. extern变量的存储位置
2.1 数据段
-
数据段:
- 使用
extern声明的全局变量存储在全局数据段,通常是程序的BSS段(未初始化全局变量)或者数据段(已初始化全局变量)。 - BSS段: 用于存储未初始化的全局变量或静态变量,这些变量在程序启动时被自动初始化为零。
- 数据段: 用于存储已初始化的全局变量或静态变量,这些变量在程序加载时被赋予初始化值。
- 使用
-
示例:
// file1.cpp int uninitialized_var; // 存储在BSS段 int initialized_var = 100; // 存储在数据段 // file2.cpp extern int uninitialized_var; extern int initialized_var;- 解释:
uninitialized_var存储在BSS段,而initialized_var存储在数据段。extern变量通过在其他文件中声明,可以访问这些全局变量。
- 解释:
3. extern "C" 的作用
3.1 C++与C的链接方式差异
-
名称修饰(Name Mangling):
- 在C++中,编译器会对函数名进行名称修饰(Name Mangling),以支持函数重载和其他C++特性。名称修饰会将函数名转换为一个包含函数名、参数类型等信息的复杂标识符,以区分不同的函数。例如,
void func(int)可能被编译器转换为_Z4funci。
- 在C++中,编译器会对函数名进行名称修饰(Name Mangling),以支持函数重载和其他C++特性。名称修饰会将函数名转换为一个包含函数名、参数类型等信息的复杂标识符,以区分不同的函数。例如,
-
C语言的链接方式:
- C语言不支持函数重载,因此在C语言中,函数名在编译时不会被修改,链接时直接使用原始的函数名。
3.2 extern "C" 的用途
-
作用:
extern "C"用于告诉C++编译器按照C语言的方式来处理指定的函数。这意味着编译器不会对这些函数名进行名称修饰,从而允许C++代码调用C语言编写的函数,或者让C语言代码调用C++函数。
-
使用场景:
- 当在C++代码中使用C语言编写的库(如标准C库)时,或者需要将C++代码暴露给C语言代码时,使用
extern "C"来避免名称修饰导致的链接错误。
- 当在C++代码中使用C语言编写的库(如标准C库)时,或者需要将C++代码暴露给C语言代码时,使用
-
示例:
// file1.c (C语言代码) void c_function() { printf("This is a C function.\n"); } // file2.cpp (C++代码) extern "C" void c_function(); // 按照C语言的方式处理该函数 void cpp_function() { c_function(); // 调用C语言函数 }- 解释: 在
file2.cpp中,extern "C"用于声明c_function函数,告诉编译器不要对它进行名称修饰,以便C++代码能够正确地调用C语言编写的函数。
- 解释: 在
3.3 extern "C" 的实际效果
-
阻止名称修饰:
- 使用
extern "C"后,函数名不会被修饰,保持C语言的函数名规则,使得C和C++代码能够相互调用。
- 使用
-
应用场景:
- 在混合C和C++代码的项目中,
extern "C"非常重要,尤其是在跨语言编程或使用C语言编写的库时。
- 在混合C和C++代码的项目中,
4. 总结
extern关键字在C和C++中主要用于声明外部变量和函数,允许在多个源文件之间共享全局变量和函数。extern变量通常存储在程序的全局数据段(BSS段或数据段)。extern "C"关键字用于告诉C++编译器按照C语言的方式处理函数,避免名称修饰,从而使C++代码能够与C语言代码进行互操作。这些机制在大型项目中尤其重要,因为它们可以有效地管理跨文件和跨语言的代码链接和调用。

1596

被折叠的 条评论
为什么被折叠?



