0

ヘッダー ファイルのラッパーとして機能する次の C ファイルがあります。

#define SOME_CONTROL_FLAG
#include "thefile.h"

これでコンパイルすると:

gcc -I. -c -o thefile.o thefile.c

9 kB のオブジェクト ファイルを取得します。ただし、代わりにこれを行うと:

gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h

3 MB のオブジェクト ファイルを取得します。それは約300倍です。これらの 2 つのコマンド ラインは、同じ結果をもたらすはずではありませんか?

4

2 に答える 2

1

一般に、異なるシンボルを使用してコンパイルすると、異なるコードがコンパイルされます

次のコードを検討してください。FOOBARが定義されている場合、ファイルにはコンパイルするコードがさらにあります (プリプロセッサが前処理した後):

#ifdef FOOBAR

int foo(int bar) {
  return bar + bar;
}

#endif

int bar(int baz) {
  return 1+baz;
}

FOOBAR を定義してコンパイルすると、出力のサイズが変わります。FOOBAR がない場合は 1232、FOOBAR がある場合は 1328 です。これは大きな違いではありませんが、大きな違いです。

$ gcc -c code.c -o code.o
$ ls -l code.o 
-rw-rw-r-- 1 user user 1232 Oct 29 13:19 code.o

$ gcc -DFOOBAR -c code.c -o code.o
$ ls -l code.o 
-rw-rw-r-- 1 user 1328 Oct 29 13:19 code.o

条件付きコードが多数ある場合、これは非常に重要になる可能性があります。たとえば、シンボルを定義すると、多くのプラットフォーム固有のコードが含まれる可能性があり、シンボルを定義しないと、関数の実装がスタブのままになる可能性があります。

さまざまなタイプのコードをコンパイルすると、さまざまなコード サイズが生成されます

注: この部分はUrhixidur の (OP の) answer に基づいています。もう少し工夫が必要だと感じました。

コンパイルされたオブジェクトのサイズが異なる可能性があるもう 1 つの側面は、GCC が実際にコンパイルしているものです。あなたの例では

gcc -I. -c -D SOME_CONTROL_FLAG -o thefile.o thefile.h

ヘッダー ファイルがコンパイルされ、GCC はc-headerファイル拡張子に基づいて言語でコンパイルされていることを検出します。ただし、ヘッダー ファイルをコンパイルしてファイルを作成しているという事実は、.oこれを C としてコンパイルすることを示唆しています。その場合、GCC の-xオプションを使用する必要があります。それについて、マニュアルページには次のように書かれています:

 -x language
           Specify explicitly the language for the following input files (rather than letting the compiler choose a default based on the file name suffix).  This option applies to all
           following input files until the next -x option.  Possible values for language are:

                   c  c-header  cpp-output
                   c++  c++-header  c++-cpp-output
                   objective-c  objective-c-header  objective-c-cpp-output
                   objective-c++ objective-c++-header objective-c++-cpp-output
                   assembler  assembler-with-cpp
                   ada
                   f77  f77-cpp-input f95  f95-cpp-input
                   go
                   java

       -x none
           Turn off any specification of a language, so that subsequent files are handled according to their file name suffixes (as they are if -x has not been used at all).

これと、最初のセクションで使用したコードに基づいて、コードを asまたは asとしてコンパイルしたときに発生する劇的なサイズの違いを観察できます。cc-header

$ gcc -c code.h -o code.o # as a header
$ ls -l code.o 
-rw-rw-r-- 1 user user 1470864 Oct 29 14:04 code.o

$ gcc -c -x c code.h -o code.o # as c code
$ ls -l code.o 
-rw-rw-r-- 1 user user 1232 Oct 29 14:04 code.o

ただし、(ヘッダーとして) コンパイルはシンボル定義の影響を受けないように見えることに注意してください。

$ gcc -c code.h -o code.o
$ ls -l code.o 
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o

$ gcc -DFOOBAR -c code.h -o code.o
$ ls -l code.o 
-rw-rw-r-- 1 user user 1470864 Oct 29 14:06 code.o
于 2013-10-29T17:21:24.947 に答える
0

gcc はその拡張子に基づいて入力をどう処理するかを決定するため、ばかげています。真の同等のコンパイル行は次のとおりです。

gcc -I. -c -D SOME_CONTROL_FLAG -x c -o thefile.o thefile.h

-xc は、.h を .c として扱うように gcc に指示します。

結果のオブジェクトファイルは、ファイルの名前が含まれているため(デバッグ情報にあると思います)、1バイトを除いて同一です。

于 2013-10-29T17:37:52.170 に答える