为什么#pragma 被认为是预处理器指令?

Why is #pragma considered a preprocessor directive?

我知道它以 # 开头,它遵循 preprocessing directives format. But does the preprocessor really care about it? The #pragma pack, #pragma once, and all other directives I know, are all proceeded by compilers. A comment in this question 甚至声明 #pragma 指令在预处理阶段仍然存在。 所以我的问题是:

  1. 既然#pragma是针对编译器的,为什么它被认为是预处理指令?仅仅是因为它以#开头吗?
  2. 预处理器真的用 #pragma 做些什么吗?

#pragma once 需要由预处理器处理,因为它的工作是替换包含保护以确保包含文件 — 使用预处理器指令 #include — 仅在给定位置出现一次。 #pragma pack,另一方面,需要毫发无损地通过预处理器,因为它是向编译器发出的关于如何在内存中布局数据的指令。

Why is #pragma considered a preprocessor directive?

因为 C 标准是这么说的。它在预处理指令一章 C17 6.10.6 中指定。除此之外,该标准故意对 #pragma 应该做什么非常模糊,因为整个目的是做某事 compiler-specific。或者,如果编译指示未被识别 - 忽略它。

未指定某个编译器如何在内部处理 pragma 的内容。

一些 pragma 显然 需要 成为 pre-processed,特别是 enables/disables 某些编译器行为的那种 #pragma warning ... 等等。很多必须在 pre-processing 期间进行评估,否则编译器将不知道如何编译代码。

Does preprocessor really do something with #pragma?

是的,它在翻译阶段 4 中评估它:“执行预处理指令,扩展宏调用,并执行 _Pragma 一元运算符表达式。”

请注意,将 pre-processor 与编译器分开主要是一个理论模型。实际上,pre-processor 和编译器通常彼此紧密集成。

直接回答您的问题:

  1. STDC FENV_ACCESSSTDC FP_CONTRACTSTDC CX_LIMITED_RANGE 之外,大多数编译指示根本不是 C-Standard 的一部分,因此它它们是否是“预处理器指令”并不重要,编译器可以自由地以它认为合适的任何方式处理它们。对于某些编译指示,在预处理阶段处理它们是有意义的,而对于其他编译指示则不需要。 pragma 背后的主要思想是它们 可以 从预处理阶段开始潜在地影响编译过程,但与宏不同,它们不会扩展到任何东西。

  2. 是的,例如在 #pragma once 的情况下,如其他答案所述。但同样,这是特定于实现的,而不是标准规定的。