C预处理器默认添加
采用以下没有导入的存根程序:
int main(void) {
return 0;
}
运行cpp它给了我:
$ cpp main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "main.c"
int main(void) {
return 0;
}
我理解它增加了# 1 "main.c"含义#line 1 "main.c"或“这是给定main.c程序的第 1 行。我很想知道所有其他cpp行的作用。例如,这个部分:
# 1 "main.c" <-- why necessary if we have this after the last line and re-defined?
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
回答
CPP 命令及其输出
当您使用该cpp命令时,C 预处理器将产生一个文本输出,这与在编译器中使用它时不同,它只会将一些结果二进制标记传递给编译器本身。
因此,您正在阅读的文本输出很像预处理器正在做什么以及如何进行的“调试”或“记录”(或“讲故事”,如果您愿意)会话。它基本上会告诉你它是如何扩展找到的宏的。
因此,正如您已经发现的那样,预处理器以以下格式的行输出行号信息和源文件名:
# linenum filename {flags}
称为linemarker,字面意思是:
这一行是在名为
filenameline的文件中找到的linenum
如果指定了任何标志,它们的范围可以从 1 到 4,含义如下:
- 1 -> 开始一个新文件。
- 2 -> 包含另一个文件后,返回到前一个文件。
- 3 -> 此文本的内容取自系统标题,因此抑制了一些警告。
- 4 -> 将文本内容包装成一个
extern "C"块
让我们一一分析这几行:
# 1 "main.c"
以下行位于line 1of main.c,没有其他标志。所以,这就像说“我开始阅读 main.c 的第 1 行”
# 1 "<built-in>"
我现在要阅读一个内置的C 预处理器指令。请注意这些是如何显示的<System Header>,但这是虚构的。因此,这一行设置了一个标准的预定义宏,例如 _ LINUX _ 或__cplusplus。
在此处阅读有关这些的更多信息
额外提示:运行cpp -dM main.c以查看所有预定义的宏。
# 1 "<command-line>"
我现在将阅读一个命令行选项,因此其中一个由-D标志设置的选项,例如-DTEST=0,甚至是命令行undefinitions,例如-UTEST. 这些再次从预处理器中作为虚构的系统头文件呈现。
在此处阅读有关预处理器选项的更多信息
# 31 "<command-line>"
在第 31 行,我正在读取来自命令行的另一个宏。(注意这些是按照找到的顺序设置的)
# 1 "/usr/include/stdc-predef.h" 1 3 4
我将读取预定义的宏文件,/usr/include/stdc-predef.h该文件位于确保该标头将像系统文件标头一样包含在内,并且它包含的符号被视为C符号。
# 32 "<command-line>" 2
我正在恢复命令行“伪头”的阅读,我将阅读它。
# 1 "main.c"
我现在将继续阅读 main.c