繁体   English   中英

是否可以强制说“ gcc”为C和C ++中相同的源代码片段生成相同的二进制文件?

[英]Is it possible to force say, `gcc`, to produce identical binaries for identical pieces of source code in C and C++?

假设有人有一个如下的C程序:

int main(int argc, char** argv)
{
    return 0;
}

我有两个带有上面源代码的文件,一个带有'c'扩展名,另一个带有'cpp'。 我分别将它们编译为C和C ++程序。 二进制文件是不同的 我以为C ++是一种“零开销”语言? :-)我试图找到的是两种不同设置的编译器标志,其中生成的二进制文件是相同的。 最好是某种语言标准,而不是任何GCC扩展。

二进制文件是不同的。

他们如何不同?

GCC会将有关所使用的原始源文件名和选项的信息嵌入文件中,因此即使内容相同,对于不同的文件名也总是会有一些差异。

如果我将程序编译为C和C ++,我看到的唯一区别是C ++版本链接到libstdc++ ,这在使用g++链接时自动发生。 如果我改用gcc进行链接,则二进制文件几乎相同。

注意,可以使用gcc编译C ++程序, gccg++二进制文件只是驱动程序,它们查看文件名并调用正确的编译器二进制文件(C1为cc1 ,C ++为cc1plus )进行实际的编译。 有关更多详细信息,请参见http://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html

这表明对于相同的源代码,汇编程序输出中的唯一区别是给出原始文件名的字符串,而目标文件的大小相同:

$ cat f.c
cat: f.c: No such file or directory
$ rm f.c
$ cat > f.c
int main(int argc, char** argv)
{
    return 0;
}
$ ln -s f.c f.cc
$ gcc f.c -S -o f.c.s
$ g++ f.cc -S -o f.cxx.s
$ diff f.c*.s
--- f.c.s       2012-08-26 13:45:58.109711329 +0100
+++ f.cxx.s     2012-08-26 13:46:00.482634256 +0100
@@ -1,4 +1,4 @@
-       .file   "f.c"
+       .file   "f.cc"
        .text
        .globl  main
        .type   main, @function
$ gcc f.c -c -o f.c.o
$ g++ f.cc -c -o f.cxx.o
$ ls -l f.c*.o
-rw-rw-r--. 1 jwakely users 1240 Aug 26 13:46 f.c.o
-rw-rw-r--. 1 jwakely users 1240 Aug 26 13:46 f.cxx.o

在最终的可执行文件中,区别在于链接方式,无论C ++标准库是否链接:

$ gcc f.c.o -o a.c.out
$ gcc f.cxx.o -o a.cxx.out
$ g++ f.cxx.o -o a.cxx.libstdcxx.out
$ ls -l a.c*.out
-rwxrwxr-x. 1 jwakely users 6323 Aug 26 13:48 a.c.out
-rwxrwxr-x. 1 jwakely users 6468 Aug 26 13:48 a.cxx.libstdcxx.out
-rwxrwxr-x. 1 jwakely users 6324 Aug 26 13:48 a.cxx.out

如果不需要C ++标准库,请不要链接到它。

这只是“我的空主体有多短”错误问题的另一个版本。

无论程序实际是什么,“基础结构”的一部分都包含启动代码和结束代码以及在任何情况下都必须链接的标准库全局对象。

测量空的主程序实际上是在测量启动/结束代码的大小。 在C和C ++中,这必须有所不同,因为C ++要准备调用main要做的事情比C要做的更多。

我不知道您所说的“零开销语言”是什么意思。 C和C ++都不是。 它们都使各自域中的开销最小化。 按照定义,唯一的零开销语言是本机代码。

当然,它们是不同的,即使是简单的事情,例如函数名,其使用c和c ++的方式也会有所不同。 c中的void foo()只是在c ++中的foo ,名称被篡改了,因为c版本没有足够的信息来处理具有不同参数列表的多个foo函数,例如void foo(int)

然后,由于大多数c / c ++程序都使用默认链接的默认标准库(对于零开销声明,可以将其禁用)。

最重要的是关于良好定义的行为的不同规则,c ++不是c的超集,并且尽管存在大量重叠,但在许多情况下它们是不同的。 例如,参见c和c ++中的sizeof('a')

结论:c和c ++编译器从相同的源代码生成相同的二进制文件,而可能的情况是极不可能发生的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM