为什么使用D选项编译头文件会导致比使用头文件的C包装器更大的文件?

时间:2013-10-29 17:13:45

标签: c gcc

我有这个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 个答案:

答案 0 :(得分:1)

一般情况下,使用不同符号编译编译不同的代码

请考虑以下代码。如果定义了FOOBAR,那么要编译的文件中有 more 代码(在预处理器预处理之后):

#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's (the OP's) answer。我觉得有点详细说明了。

可能导致不同编译对象大小的另一个方面是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).

基于此,以及我在第一部分中使用的代码,我们可以观察到将代码编译为c或{{1}时发生的剧烈的大小差异}:

c-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

答案 1 :(得分:0)

因为gcc根据其扩展决定如何处理输入,所以很傻。真正的等效编译行是:

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

其中-x c告诉gcc将.h视为.c

除了一个字节之外,生成的目标文件是相同的,因为包含了文件的名称(我想在调试信息中)。