2017-01-30 91 views
2

我正在使用Gnu cc编译器Gcc来编译我的C程序。考虑一个程序,预处理器行由预处理器处理时会发生什么? - '.i'文件

#include <stdio.h> 
int main(){ 
    return 0; 
} 

现在,当我预处理使用上面的代码,

cpp sample.c > sample.i 

我得到了很多的内容sample.i我还没有包括在内。说,'stdio.h'文件是预处理。如果是这样的话,

问题1:

为什么有这么多的线路在我的预处理文件? I 尚未使用任何标准库函数和宏。

问题2:

谁能解释当预处理proccess C文件到底发生了什么(我在我的 '*。我' 文件得到的内容)

编译器:GCC

操作系统:Ubuntu的

感谢

+0

它从字面上打开包含文件,并在原地复制内容。如果''还包含其他一些文件,那些文件也会被复制,等等。这就是为什么你有这么多东西,你不认为你要求。 – BoBTFish

回答

4

为什么有这么多的线路在我预处理文件一个很好的(短)指导?我没有使用任何标准库函数和宏。

预处理只是编译过程的一部分。它或多或少是一个简单的文本替换,在预处理阶段没有涉及更复杂的事情。预处理器不知道或不在乎您是否在代码程序中使用了任何标准函数。优化器(作为编译过程的一部分)可能会“删除”不需要的部分。但预处理器不会那样做。 它会对你包含的所有头文件和通过头文件包含的其他头文件进行预处理,等等。

谁能解释到底发生了什么,当预处理过程中的C文件(我在我的“*。我”文件得到的内容)

预处理涉及相当多的任务:宏替换,条件编译,字符串化,字符串连接等。 您可以详细了解更多关于cpp这里:https://gcc.gnu.org/onlinedocs/cpp/

3

的preproces sor命令#include "aFile.h"会将来自aFile.h的孔内容放入您的cpp文件中。这正是预处理指令所在的地方。这就是为什么您可以使用aFile.h定义的功能的原因。

,如果你是兴趣了解更多的预处理,对cplusplus.com

+1

为什么复制stdio.h文件的内容,虽然我没有使用任何与它有关的东西(没有库函数或宏)? –

+1

预处理器不关心。 – LogicStuff

+1

你还没有使用它,但你可以。如果你不需要它们,你可以删除include语句。 – Soeren

1

1)不得使用它们,但你已经在1号线

#include <stdio.h> 

这就是你看到来自哪个包括他们。尝试将其删除以查看差异。

2)预处理器读取您的C文件并处理您声明的所有预处理器指令。所有预处理器指令都以'#'符号开头。 '#include'将用给定文件的内容替换这一行。你也有经典的'#ifndef'和'#define'指令。后者等于“if”语句,其允许激活的码的一部分仅当符号被定义

#ifndef _SOME_SYMBOL_ 
#define _SOME_SYMBOL_ 

#ifndef WIN32 
#include <some_file.h> 
#else 
#include <some_other_file.h> 
#endif 

int main() { return 0;} 

#endif //endof _SOME_SYMBOL_ 

#ifndef _SOME_SYMBOL_ 
#define _SOME_SYMBOL_ 

// this second function is ignored 
int main() { return 0;} 

#endif //endof _SOME_SYMBOL_ 

当预处理器读取上述文件中,符号“_SOME_SYMBOL_”是未知的,所以预处理器初始化它。接下来它包括文件是否知道WIN32。通常这种符号是通过命令行传递的。所以你的代码的一部分被动态激活或停用。

预处理程序输出这个

void some_other_function_from_some_other_file(){} 

int main() { return 0;} 
3

预处理程序所做的文本替换。 #include <stdio.h>的净效应是用<stdio.h>的内容替换#include <stdio.h>行。

实际上,<stdio.h>包含的各种功能的若干声明的(例如fprintf()fscanf()),变量声明(例如stdoutstdin),以及一些宏定义(其在后面代码中使用时,会导致文本替换)。

预处理器被指定为编译阶段,它将源代码作为输入,根据需要替换文本(例如,我所描述的#include,宏扩展等),并输出结果源代码。这输出你是什么引导到sample.i

预处理器的输出是输入到编译的稍后阶段,这实际上明白声明,定义,报表等

编译的阶段是顺序 - 他们一个接一个地发生,而不是一次全部发生。因此编译的后期阶段没有任何信息返回到预处理器。编译的后期阶段检测是否使用了声明等。但是,由于它不能将这些信息反馈给预处理器(并且预处理器是无法使用这些信息的无知程序),因此预处理器无法知道声明未被使用并将其过滤掉。