c++ - 当我用 libgcc 替换 libstdc++ 时,为什么我的 C++ 程序可以正确链接

标签 c++ c name-mangling

目前我在 wikipeida 上读到一篇关于名称修改的文章( link )。在那篇文章中,我了解到常见的extern "C" idiom 用于保护 C++ 源文件中的 C 代码不被破坏,这使得这些源代码不兼容与原始 C 库链接。

所以我做出以下推理:

如果我写这样的代码:

#include<stdio.h>
int main()
{
    printf("Hello World\n");
    return 0;
}

并使用命令 g++ test.cpp -o test 编译它,那么毫无疑问就可以编译成功了。我们不必附上printf()extern "C" ,尽管 printf()是一个C函数。 那是因为还有一个printf()libstdc++ ,与libgcc中的不同。 .

到目前为止,一切顺利。

但我发现事实并非如我所想。

我做了一些实验:

我删除了所有 libstdc++/usr/lib 下,其中包括

  • /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a
  • /usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.so
  • /usr/lib/x86_64-linux-gnu/libstdc++.so.6
  • /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19

然后我复制 libgcc并将其放在 libstdc++ 的位置下已经存在(否则链接器会提示libstdc++未找到)

$sudo cp ./gcc/x86_64-linux-gnu/4.8/libgcc.a ./gcc/x86_64-linux-gnu/4.8/libstdc++.a

但是,上面的代码编译时,没有 extern "C" !!!

这是为什么呢?它不应该抛出一个未解析的引用或类似的东西,因为 printf() ,已被 C++ 编译器破坏,与 printf() 不兼容在李libgcc

<小时/>

有人告诉我为什么我的问题被否决了吗?

<小时/>

最佳答案

您的extern "C"存在,尽管它是隐藏的。

如果你查看stdio.h ,你会注意到这条线

 __BEGIN_DECLS

(我的系统上的第 29 行*)依次扩展为

# define __BEGIN_DECLS       extern "C" {

(在我的系统上 sys/cdefs.h 中的第 98 行)如果您在 C++ 模式下编译,则不进行任何其他操作。因此标准库头会为您进行包装。

删除 C++ 标准库没有任何影响,因为这些 C 函数位于 C 标准库中,并且由于所有包装都正确完成,链接器可以找到并使用它们。

现在当然这是一个实现细节,一般来说,使用 <stdio.h>必须有效,因为标准是这么说的(目前,它已被弃用)。编译器如何实现这一点并没有强制规定。

<小时/>

*gcc6.1.1 为 Arch Linux 打包

关于c++ - 当我用 libgcc 替换 libstdc++ 时,为什么我的 C++ 程序可以正确链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37239763/

相关文章:

c++ - C++中与Arduino的串行通信超时

将 char 数组转换为一个 int

c - 访问不同源文件中的结构

c - 如何在调用之间的 Ruby 扩展中将 C 对象保留在内存中?

python - 正确使用ctypes来调用_Py_Mangle?

c++ - 在运行时修改模板函数的名称 - 可能吗?

c++ - 通用工厂设计模式的实现

c++ - SDL_Delay 在 for 循环中不起作用

linker - C++ 中的符号 – 它们是否在非调试版本中导出?

c++ - 如何将结构属性转换为 C++ 中的指针引用?