说一说extern“C”

参考回答

extern "C" 是 C++ 中用于告诉编译器按照 C 语言的方式来处理函数和变量的声明,特别是与 C 语言代码进行链接时使用。它的作用是禁用 C++ 的名称修饰(name mangling),使得 C++ 编译器生成符合 C 语言标准的符号名称,从而能够让 C++ 代码与 C 语言代码进行链接。

通常,在 C++ 中声明一个 C 语言的函数时,需要使用 extern "C" 来保证编译器按 C 语言的方式进行处理。例如:

extern "C" {
    #include "some_c_header.h"  // 包含C语言头文件
    void c_function();           // C语言函数声明
}

详细讲解与拓展

1. 名称修饰(Name Mangling)

C++ 支持函数重载、类的成员函数等特性,因此它需要对函数名进行“名称修饰”以区分不同的函数。例如,在 C++ 中,如果有多个同名但参数不同的函数,编译器会在函数名后加上一些编码来区分这些函数。

例如,假设我们有两个函数:

void foo(int a);
void foo(double b);

编译器可能会将它们修饰为如下的符号:

foo_int(int)
foo_double(double)

而 C 语言并没有函数重载的概念,因此函数名不会被修改,保持原样。

2. extern "C" 的作用

当我们使用 extern "C" 时,C++ 编译器就会按照 C 语言的规则来处理这些函数声明,避免名称修饰的发生。这样做可以确保 C++ 编译器生成的符号与 C 编译器一致,使得 C++ 代码可以与 C 语言代码进行链接。

extern "C" void c_function();  // 告诉编译器按照C语言规则处理

3. 使用场景

  • C++ 与 C 代码的混合:当你在 C++ 项目中需要调用 C 语言的函数库时,或者将 C 语言的函数暴露给 C++ 代码时,需要使用 extern "C"
  • C++ 与其他语言的接口:在一些跨语言编程的场景下,C 语言风格的链接可以确保代码能够正确链接到外部语言的库(如 Python、Fortran 等)。
  • 防止名称冲突:在不同的语言中,函数和变量的命名规则可能不同,extern "C" 帮助避免命名冲突,确保正确链接。

4. 例子

  • C++ 调用 C 函数

    假设有一个 C 语言的库文件 example.c,其中有一个函数 sum

    // example.c
    int sum(int a, int b) {
      return a + b;
    }
    

    在 C++ 中调用这个函数时,我们需要使用 extern "C" 来确保函数名不被 C++ 修饰:

    // example.cpp
    extern "C" {
      int sum(int, int);  // 声明C语言的sum函数
    }
    
    int main() {
      int result = sum(3, 5);  // 调用C语言的sum函数
      return 0;
    }
    
  • C 函数头文件

    在 C 语言中,如果要确保头文件可以被 C++ 代码正确包含,通常也会使用 extern "C",防止 C++ 编译器对函数声明进行名称修饰:

    // example.h
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int sum(int, int);
    
    #ifdef __cplusplus
    }
    #endif
    

    这样,在 C++ 文件中包含 example.h 时,C++ 编译器会按照 C 语言规则处理函数。

5. extern "C"extern 的区别

  • extern 是用来声明在其他文件中定义的变量或函数,表示这些变量或函数在当前文件外部定义,不会分配内存。例如:
    extern int var;  // 声明在其他文件中定义的变量
    
  • extern "C" 除了声明外,还改变了 C++ 编译器的行为,使其按照 C 语言的链接规则处理函数和变量。

总结

extern "C" 主要用于在 C++ 中引用 C 语言代码或将 C++ 代码暴露给 C 语言使用。它避免了 C++ 编译器的名称修饰,确保符号名称在 C 和 C++ 编译器中保持一致,进而保证代码可以正常链接和调用。

发表评论

后才能评论