【面试】解释一下extern关键字的作用吗?另外,extern变量存储在哪个数据段,以及为什么要使用extern “C“?

面试模拟场景

面试官: 你能解释一下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语言的链接方式:

    • C语言不支持函数重载,因此在C语言中,函数名在编译时不会被修改,链接时直接使用原始的函数名。

3.2 extern "C" 的用途

  • 作用:

    • extern "C"用于告诉C++编译器按照C语言的方式来处理指定的函数。这意味着编译器不会对这些函数名进行名称修饰,从而允许C++代码调用C语言编写的函数,或者让C语言代码调用C++函数。
  • 使用场景:

    • 当在C++代码中使用C语言编写的库(如标准C库)时,或者需要将C++代码暴露给C语言代码时,使用extern "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语言编写的库时。

4. 总结

extern关键字在C和C++中主要用于声明外部变量和函数,允许在多个源文件之间共享全局变量和函数。extern变量通常存储在程序的全局数据段(BSS段或数据段)。extern "C"关键字用于告诉C++编译器按照C语言的方式处理函数,避免名称修饰,从而使C++代码能够与C语言代码进行互操作。这些机制在大型项目中尤其重要,因为它们可以有效地管理跨文件和跨语言的代码链接和调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值