在C++中名称修饰和extern “C”

C++支持函数重载,即可以有多个具有相同名称和参数差异的函数。C++编译器在生成目标代码时如何区分不同的功能?它通过添加有关参数的信息来更改名称。这种将附加信息添加到函数名称的技术称为名称处理。C++标准没有指定任何特殊的名称处理技术,因此不同的编译器可能会将不同的信息附加到函数名称中。

考虑以下函数f()的声明

int  f (void) { return 1; } 
int  f (int)  { return 0; } 
void g (void) { int i = f(), j = f(0); } 

A C++ compiler may mangle above names to following (Source: Wiki)

一个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的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

编译器错误的原因很简单,C++编译器更改了printf的名称,但找不到带有新名称的函数定义。

问题的解决方案是C++中的extern “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,string.h,..等)在extern “ C”块中都有其声明。

#ifdef __cplusplus  
extern "C" { 
#endif 
    /* Declarations of this file */
#ifdef __cplusplus 
} 
#endif 

以下是上面讨论的要点

1.由于C++支持函数重载,因此必须在函数名称中添加其他信息(称为名称重整),以避免二进制代码中的冲突。

2.可能无法在C中更改函数名称,因为C不支持函数重载。为了避免链接问题,C++支持extern “C”块。C++编译器确保未更改extern “C”块内的名称。

六一编程网

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Next Post

在Python中从控制台获取输入

周四 3月 26 , 2020
Python中的控制台是什么? 控制台(也称为Shell)基本上是一个命令行解释器,它从用户那里获取 […]