extern "C" 是 C++ 中用于与 C 语言进行互操作的重要关键字。它主要用于告诉编译器在链接阶段如何处理函数或变量名。下面是详细介绍 extern "C" 的背景、用途、以及使用方法:

# 1. 背景:

  • 在 C 和 C++ 中,函数和变量的符号是通过名字来链接的,但 C++ 使用了 "名字修饰"(Name Mangling)来支持函数重载等特性。这种修饰会导致编译器生成的函数名不再是原始的函数名,而是带有类名、参数类型等信息的复杂字符串。
  • 例如,C++ 中一个函数 int add(int, int) 可能会被编译器修饰成 _Z3addii 或其他复杂的符号,而 C 语言中相同的函数名则是简单的 add
  • 由于 C 语言不支持函数重载和名字修饰,如果在 C++ 代码中直接调用 C 语言的函数,编译器会找不到匹配的符号,导致链接错误。

# 2. extern "C" 的用途:

  • 消除名字修饰:
    extern "C" 告诉编译器不要对函数进行名字修饰,而是保持 C 语言的链接方式,这样 C++ 代码就能正确链接 C 语言代码中的符号。
  • 函数声明:
    当在 C++ 中声明 C 语言函数时使用 extern "C" ,以确保链接器找到正确的函数符号。
  • 用于 C++ 与 C 语言混合编程:
    尤其是在大型项目或跨语言项目中,经常需要 C++ 调用 C 语言的库,或者反过来,这时就需要 extern "C" 来管理符号。

# 3. 使用方法:

  • 单个函数声明:

    1
    2
    // 这是在 C++ 代码中声明一个 C 语言的函数
    extern "C" void myCFunction(int arg);

    这样做会告诉编译器 myCFunction 是一个 C 语言函数,编译器将不会对它的名字进行修饰。

  • 多函数声明:

    1
    2
    3
    4
    extern "C" {
    void func1(int);
    int func2(double);
    }

    使用大括号可以一次性声明多个 C 函数,使它们都以 C 语言的链接方式处理。

  • C 语言头文件的引用:

    1
    2
    3
    4
    5
    // C 语言头文件可能没有使用 extern "C"
    // 需要在 C++ 代码中做处理
    extern "C" {
    #include "my_c_library.h"
    }

    这确保了所有在 my_c_library.h 中声明的函数在 C++ 中被正确识别为 C 语言函数。

# 4. 注意事项:

  • 对变量的作用:
    extern "C" 也可以用于变量声明,确保变量名在链接时不被修饰。
  • 不能用于类:
    由于 C 语言不支持类,因此不能对类使用 extern "C"
  • 多次声明:
    在多个地方对同一函数使用 extern "C" 是安全的,但在定义时需要确保只有一个链接的定义。
  • 与 C++ 函数混合:
    extern "C" 不能消除 C++ 特性,比如函数重载、默认参数等。这些特性在 C 语言中是不支持的。

# 5. 示例:

  • 假设有一个 C 语言函数实现如下:
    1
    2
    3
    4
    5
    6
    // my_functions.c
    #include <stdio.h>

    void greet(const char* name) {
    printf("Hello, %s!\n", name);
    }
  • 在 C++ 中调用这个函数:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // main.cpp
    extern "C" {
    void greet(const char* name);
    }

    int main() {
    greet("World");
    return 0;
    }
  • 这段代码编译时不会出现链接错误,因为 greet 函数在 C++ 中被正确识别为 C 语言函数。

extern "C" 是在 C++ 和 C 混合编程中不可或缺的工具,确保了两种语言可以无缝协作。

更新于

请我喝杯咖啡吧~

Rick 微信支付

微信支付

Rick 支付宝

支付宝