该标准允许#pragma做什么?

时间:2013-07-07 10:21:42

标签: c++ language-lawyer

在C ++(和C)中,我们有#pragma指令,它基本上具有实现定义的效果。但是,该指令可能有什么限制吗? (请注意,我在询问标准允许的内容,而不是实际编译器实际执行的内容。)

我确定#pragma可能会这样做:

  • 允许选择几个编译选项中的一个,这些选项都会产生有效的C ++ - 例如,选择几个可用的ABI中的一个,或者切换某些实现定义的选项。

我猜是允许的,但我不确定:

  • 允许编译器在不发出诊断的情况下接受其他非法代码(例如,编译器可能决定支持新的内置类型long long long,但使用该代码的任何代码都必须发出诊断;然后可以使用例如#pragma long long long来抑制此诊断。

  • 允许编译器拒绝其他合法代码,例如可能有#pragma strict导致编译器将某些库函数和/或语言结构的使用标记为错误,这些函数和/或语言结构被认为是不安全的。

我实际上怀疑是允许的,但我也不确定:

  • 允许编译器将合法代码的语义更改为不同的语句(例如,假设编译器供应商认为for条件是后置条件(如do中... while),并定义#pragma for postcondion以相应地切换for的含义。

我怀疑后者的原因是允许编译器忽略它无法识别的任何编译指示,因此编译指示的语义更改会导致同一程序在不同编译器上具有不同的语义。

然而,标准实际允许什么?是否有允许的内容,但我的上面列表中没有涵盖这些内容?

3 个答案:

答案 0 :(得分:5)

标准非常明确:

  

[cpp.pragma] 表单的预处理指令

#pragma pp-tokensopt new-line
     

导致实现以实现定义的方式运行。该行为可能导致转换失败或导致转换程序或生成的程序以不合规的方式行为。将忽略实现无法识别的任何编译指示。

因此,编译器可以在看到#pragma时完成任何操作。

答案 1 :(得分:3)

C ++标准的n3337版本说

  

表单的预处理指令   #pragma pp-tokensopt new-line    导致实现以实现定义的方式运行。   该行为可能导致翻译失败或导致翻译或   生成的程序以不符合的方式运行。将忽略实现无法识别的任何编译指示。

我认为这允许编译器在#pragma的情况下几乎做任何想做的事情。 "翻译失败"和"翻译或结果程序以不合规的方式行事"涵盖了广泛的选择。

当然,这并不意味着让编译器做出疯狂的事情是明智之举。事情 - 它可能"心烦意乱"人,但从标准的角度来看,它是完全有效的。

答案 2 :(得分:1)

只要记录在案,编译器就可以完成所有操作。在看到任何编译指示时,一个非常古老的gcc版本,用于停止编译并尝试定位并启动当时存在的文本模式游戏之一。这是完全符合标准的,因为在用户指南中有关于它的部分。