C++支持函数重载,即,可以有多个具有相同名称和不同参数的函数。 C++编译器在生成目标代码时如何区分不同的功能-它通过添加有关自变量的信息来更改名称。这种将附加信息添加到函数名称的技术称为名称处理。 C++标准没有指定任何特殊的名称处理技术,因此不同的编译器可能会将不同的信息附加到函数名称中。
考虑以下函数f()的声明
int f (void) { return 1; }
int f (int) { return 0; }
void g (void) { int i = f(), j = f(0); }
C++编译器可能会将上面的名称混为一谈(来源:Wiki)
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的printf()函数的C++程序。
// Save file as .cpp and use C++ compiler to compile it
int printf(const char *format,...);
int main()
{
printf("GeeksforGeeks");
return 0;
}
输出:
undefined reference to `printf(char const*, ...)'
ld returned 1 exit status
编译器错误的原因很简单, printf的名称已由C++编译器更改,并且找不到带有新名称的函数定义。
问题的解决方案是C++中的外部“ C”。当将某些代码放在extern“ C”块中时,C++编译器确保函数名称不被破坏-与C编译器一样,编译器将发出一个名称不变的二进制文件。
如果将上述程序更改为以下程序,则该程序可以正常工作并在控制台上打印“ GeeksforGeeks”。
// Save file as .cpp and use C++ compiler to compile it
extern "C"
{
int printf(const char *format,...);
}
int main()
{
printf("GeeksforGeeks");
return 0;
}
输出:
GeeksforGeeks
因此,所有C样式头文件(stdio.h,字符串.h,..等)在extern“ C”块中都有其声明。
#ifdef __cplusplus
extern "C" {
#endif
/* Declarations of this file */
#ifdef __cplusplus
}
#endif
以下是上面讨论的要点
1.由于C++支持函数重载,因此必须在函数名称中添加其他信息(称为名称重整),以避免二进制代码中的冲突。
2.由于C不支持函数重载,因此不能在C中更改函数名称。为避免链接问题,C++支持外部“ C”块。 C++编译器确保未更改外部“ C”块内的名称。