gcc标志-include在编译.i或.ii文件时被忽略

时间:2019-06-14 14:25:21

标签: c gcc preprocessor

我最近发现,如果文件结尾为.i或.ii,gcc会跳过预处理,并决定尝试一下。编译不包含stdio.h的hello world程序:

gcc -Wall file.c; # compiles with preprocessor, implicit declaration of puts
gcc -Wall file.i; # compiles without preprocessor, implicit declaration of puts 

没有预处理器指令,我无法包含stdio.h,但我记得gcc的-include标志可用于“强制包含”标头。它导致了以下测试:

gcc -Wall -include stdio.h file.c; # no warnings, "hello world". hooray
gcc -Wall -include stdio.h file.i; # implicit declaration of puts WAIT WHAT?!

我发现奇怪的是,如果不经过预处理就编译文件,gcc为何不包含stdio.h。更奇怪的是,如何不发出警告; -include stdio.h没有明显的效果,这充其量是对gcc的错误使用。

为什么不起作用?

GCC版本6.3.0。

3 个答案:

答案 0 :(得分:1)

-include列在Preprocessor Options下:

  

3.12控制预处理器的选项

     

这些选项控制C预处理程序,该处理器在实际编译之前在每个C源文件上运行。

     

[...]

     

-include file

     

处理 file 就像#include "file"出现在主源文件的第一行一样。 [...]

但是,对于.i个文件,预处理器永远不会运行,因此该选项无效。

GCC通常不会警告无效的选项。您还可以运行gcc -Wall -funsigned-char foo.o,它甚至不会调用编译器。 -Wall-funsigned-char会被忽略。

您可以将编译视为管道:

  1. C代码(.c)通过预处理器,该预处理器产生...
  2. 预处理的C代码(.i),由生成...的编译器处理。
  3. 汇编代码(.s),由产生...的汇编器处理。
  4. 目标代码(.o),由链接程序处理,为您提供...
  5. 可执行文件。

文件名告诉GCC从哪个阶段开始。

选项可用于告知GCC在哪里停止:

  • -P在预处理后停止
  • -S在编译后停止
  • -c组装后停止

其他选项将传递到管道中的相应阶段。如果那部分流水线永远都不会运行,那就什么也没发生。

答案 1 :(得分:0)

来自GCC documentation

  

-包括 file

     

处理 file 就像#include "file"出现在主源文件的第一行一样。但是,搜索 file 的第一个目录是预处理程序的工作目录代替,该目录包含主源文件。如果没有找到,则照常在#include "…"搜索链的其余部分中搜索它。

     

如果提供了多个-include options,则文件将按照在命令行中出现的顺序包括在内。

第一个短语

  

处理文件就像#include "file"出现在主源文件的第一行一样。

表示您会期望看到的行为。

如果GCC不应用预处理指令,则它将不包含该文件,因为它不会盲目地将stdio.h的内容添加到正在编译的文件的开头,因此它的作用就像添加了预处理器的include指令。

答案 2 :(得分:0)

这很有意义。 .i文件已经过预处理,因此没有预处理步骤,因此没有包含。

对已预处理的文件进行操作是一个非常高级的主题,因此也许他们只是假设任何这样做的人都知道自己在做什么。

或者也许只是疏忽,您应该得到警告。