编译 .i 或 .ii 文件时忽略 gcc 标志 -include
gcc flag -include ignored when compiling .i or .ii files
我最近发现如果文件结尾是 .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 标志可用于 "force include" headers。它导致了以下测试:
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.
-include file
Process file as if #include "file"
appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor’s working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "…"
search chain as normal.
If multiple -include options
are given, the files are included in the order they appear on the command line.
第一个短语
Process file as if #include "file"
appeared as the first line of the primary source file.
表示人们会期待您看到的行为。
如果 GCC 不应用预处理指令,它不会包含该文件,因为它不会盲目地将 stdio.h
的内容添加到正在编译的文件的前面,它就像它添加了预处理器包含指令。
有道理。 .i 文件已经过预处理,所以没有预处理步骤,所以没有包含。
对已经预处理过的文件进行操作是一个非常高级的主题,所以他们可能只是假设任何执行此操作的人都知道他们在做什么。
或者这可能只是一个疏忽,你应该得到警告。
-include
列在 Preprocessor Options:
下
3.12 Options Controlling the Preprocessor
These options control the C preprocessor, which is run on each C source file before actual compilation.
[...]
-include <em>file</em>
Process file as if #include "file"
appeared as the first line of the primary source file. [...]
但是,对于 .i
文件,预处理器从不 运行s,因此该选项无效。
GCC 通常不会对无效的选项发出警告。您还可以 运行 gcc -Wall -funsigned-char foo.o
,它甚至不调用编译器。 -Wall
和 -funsigned-char
将被忽略。
你可以把编译想象成一个管道:
- C 代码 (
.c
) 通过预处理器,生成 ...
- 预处理的 C 代码 (
.i
),由编译器处理生成 ...
- 汇编程序代码 (
.s
),由汇编程序处理生成 ...
- 目标代码(
.o
),由链接器处理,给你...
- 一个可执行文件。
文件名告诉 GCC 从哪个阶段开始。
选项可用于告诉 GCC 在何处停止:
-P
预处理后停止
-S
编译后停止
-c
组装后停止
其他选项被传递到管道中的相应阶段。如果管道的那部分从不 运行s,则什么也不会发生。
我最近发现如果文件结尾是 .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 标志可用于 "force include" headers。它导致了以下测试:
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.
-include file
Process file as if
#include "file"
appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor’s working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the#include "…"
search chain as normal.If multiple
-include options
are given, the files are included in the order they appear on the command line.
第一个短语
Process file as if
#include "file"
appeared as the first line of the primary source file.
表示人们会期待您看到的行为。
如果 GCC 不应用预处理指令,它不会包含该文件,因为它不会盲目地将 stdio.h
的内容添加到正在编译的文件的前面,它就像它添加了预处理器包含指令。
有道理。 .i 文件已经过预处理,所以没有预处理步骤,所以没有包含。
对已经预处理过的文件进行操作是一个非常高级的主题,所以他们可能只是假设任何执行此操作的人都知道他们在做什么。
或者这可能只是一个疏忽,你应该得到警告。
-include
列在 Preprocessor Options:
3.12 Options Controlling the Preprocessor
These options control the C preprocessor, which is run on each C source file before actual compilation.
[...]
-include <em>file</em>
Process file as if
#include "file"
appeared as the first line of the primary source file. [...]
但是,对于 .i
文件,预处理器从不 运行s,因此该选项无效。
GCC 通常不会对无效的选项发出警告。您还可以 运行 gcc -Wall -funsigned-char foo.o
,它甚至不调用编译器。 -Wall
和 -funsigned-char
将被忽略。
你可以把编译想象成一个管道:
- C 代码 (
.c
) 通过预处理器,生成 ... - 预处理的 C 代码 (
.i
),由编译器处理生成 ... - 汇编程序代码 (
.s
),由汇编程序处理生成 ... - 目标代码(
.o
),由链接器处理,给你... - 一个可执行文件。
文件名告诉 GCC 从哪个阶段开始。
选项可用于告诉 GCC 在何处停止:
-P
预处理后停止-S
编译后停止-c
组装后停止
其他选项被传递到管道中的相应阶段。如果管道的那部分从不 运行s,则什么也不会发生。