0

次のような C プログラムがあるとします。

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

上記のソース コードを含む 2 つのファイルがあります。1 つは拡張子が 'c' で、もう 1 つは 'cpp' です。それぞれ C および C++ プログラムとしてコンパイルします。バイナリは異なります。C++ は「オーバーヘッドゼロ」の言語だと思いましたか? :-) 私が見つけようとしているのは、結果のバイナリが同じである 2 つの異なるセットアップのコンパイラ フラグです。あらゆる種類の GCC 拡張機能ではなく、何らかの言語標準を使用することをお勧めします。

4

3 に答える 3

6

バイナリは異なります。

それらはどのように違うのですか?

GCC は、元のソース ファイル名と使用されたオプションに関する情報をファイルに埋め込むため、内容が同じであっても、ファイル名が異なると常にいくつかの違いがあります。

プログラムを C および C++ としてコンパイルすると、C++ バージョンが にリンクされていることがわかります。libstdc++これは、を使用してリンクすると自動的に発生しますg++。代わり gccにリンクを使用すると、バイナリはほぼ同じになります。

gccC++ プログラムのコンパイルに使用できることに注意してください。gccおよびg++バイナリは、ファイル名を確認し、正しいコンパイラ バイナリ ( cc1C の場合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++ には、C が実際に行う必要があるよりも、main を呼び出す準備をするために行うべきことがはるかに多いからです。

「ゼロオーバーヘッド言語」とはどういう意味かわかりません。C も C++ もそうではありません。どちらも、それぞれのドメインでのオーバーヘッドを最小限に抑えます。唯一のゼロ オーバーヘッド言語は、定義上、ネイティブ マシン コードです。

于 2012-08-26T12:40:20.763 に答える
1

もちろん、関数名のような単純なものでさえ、c と c++ では異なる方法で処理されます。 void foo()in c は単にfooc++ にあり、c バージョンには のような異なるパラメーター リストを持つ複数の foo 関数を処理するのに十分な情報が含まれていないため、その名前はマングルされますvoid foo(int)

次に、ほとんどの c/c++ プログラムで使用されているため、デフォルトでリンクされているさまざまな標準ライブラリがあります (ゼロ オーバーヘッドの主張のために、これを無効にすることができます)。

最も重要なのは、明確に定義された動作に関するさまざまな規則です。c++ は c のスーパーセットではなく、多くの重複がありますが、異なる場合が多くあります。たとえばsizeof('a')、c および c++ を参照してください。

結論: c および c++ コンパイラが同一のソース コードから同一のバイナリを生成する可能性は非常に低いです。

于 2012-08-26T13:11:25.077 に答える