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


以上是C预处理器默认添加的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>