目前我在 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/