「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」
C++ 支持函数重载,即可以有多个同名但不同参数的函数。C++ 编译器在生成目标代码时如何区分不同的函数——它通过添加有关参数的信息来更改名称。这种向函数名称添加附加信息的技术称为Name Mangling。C++ 标准没有指定任何特定的名称修改技术,因此不同的编译器可能会向函数名称附加不同的信息。
考虑以下 Name Mangling 示例,其中包含函数f() 的各种声明 :
int f(void) { return 1; } int f(int) { return 0; } void g(void) { int i = f(), j = f(0); } 复制代码
一些 C++ 编译器可能会将上述名称改写为以下名称,
int __f_v(void) { return 1; } int __f_i(int) { return 0; } void __g_v(void) { int i = __f_v(), j = __f_i(0); } 复制代码
注意: C 不支持函数重载,因此,当我们在 C++ 中链接 C 代码时,我们必须确保符号的名称不被更改。
从 C++ 链接时如何处理 C 符号?
在 C 中,名称可能不会被修改,因为它不支持函数重载。那么当我们在 C++ 中链接 C 代码时,如何确保符号的名称不被更改。例如,请参阅以下使用 C 的 printf() 函数的 C++ 程序。
#include <stdio.h> int printf(const char* format, ...); int main() { printf("haiyong"); return 0; } 复制代码
上述程序产生错误。
解释: 编译错误的原因很简单,c++编译器修改了printf() 的名字,没有找到新名字的函数定义。
解决方案: C++ 中的 Extern “C”
当一些代码被放入 extern “C” 块时,C++ 编译器确保函数名是未修改的——编译器发出一个名称不变的二进制文件,就像 C 编译器会做的那样。
如果我们把上面的程序改成下面这样,程序就可以正常工作并在控制台上打印“haiyong”(如下所示)。
#include <bits/stdc++.h> using namespace std; extern "C" { int printf(const char* format, ...); } int main() { printf("haiyong"); return 0; } 复制代码
输出
haiyong 复制代码
因此,所有 C 风格的头文件(stdio.h、string.h 等)在 extern “C”块中都有它们的声明。
#ifdef __cplusplus extern "C" { #endif // Declarations of this file #ifdef __cplusplus } #endif 复制代码
以下是上面讨论的要点:
1. 由于 C++ 支持函数重载,因此必须在函数名称中添加附加信息(称为 Name mangling)以避免二进制代码中的冲突。
2. C 中不能更改函数名称,因为它不支持函数重载。为了避免链接问题,C++ 支持 extern “C” 块。C++ 编译器确保 extern “C” 块内的名称不会更改。
如果您发现任何不正确的内容,或者您想分享有关上述主题的更多信息,请发表评论。