0

假设有一个 C 程序,如下所示:

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

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

4

3 回答 3

6

二进制文件是不同的。

它们有何不同

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

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

注意,您可以使用它gcc来编译 C++ 程序,gccg++二进制文件只是查看文件名并调用正确的编译器二进制文件(cc1对于 C,cc1plus对于 C++)进行实际编译的驱动程序。有关详细信息,请参阅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++ 标准库,请不要链接到它。

于 2012-08-26T12:40:39.387 回答
2

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

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

测量一个空的主程序,实际上是测量启动/结束代码的大小。这在 C 和 C++ 中肯定是不同的,因为 C++ 准备调用 main 比 C 实际需要做的事情要多得多。

我不知道您所说的“零开销语言”是什么意思。C 和 C++ 都不是。它们都将各自域中的开销降至最低。根据定义,唯一的零开销语言是本机机器代码。

于 2012-08-26T12:40:20.763 回答
1

当然它们是不同的,即使是像函数名这样简单的东西,c 和 c++ 的处理方式也不同。 void foo()在 c 中只是foo在 c++ 中,该名称会被破坏,因为 c 版本不包含足够的信息来处理具有不同参数列表的多个 foo 函数,例如void foo(int).

然后是默认链接的不同标准库,因为它们被大多数 c/c++ 程序使用(对于您的零开销声明,可以禁用)。

最重要的是关于定义明确的行为的不同规则,c++ 不是 c 的超集,虽然有大量重叠,但在许多情况下它们是不同的。参见sizeof('a')c 和 c++ 中的示例。

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

于 2012-08-26T13:11:25.077 回答