5

在 C++(和 C)中,我们有#pragma基本上具有实现定义效果的指令。但是,该指令的作用是否有任何限制?(请注意,我问的是标准允许什么,而不是真正的编译器实际做了什么。)

我确定#pragma可能会做的事情:

  • 允许选择所有导致有效 C++ 的几个编译选项之一 - 例如,选择几个可用 ABI 之一,或切换某些实现定义的选项。

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

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

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

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

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

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

但是,该标准实际上允许什么?有没有什么是允许的,但我上面的清单没有涵盖?

4

3 回答 3

5

标准非常明确:

[cpp.pragma]形式的预处理指令

#pragma pp-tokensopt new-line

导致实现以实现定义的方式运行。该行为可能会导致翻译失败或导致翻译器或生成的程序以不合格的方式运行。任何未被实现识别的编译指示都会被忽略。

因此,编译器可以在看到#pragma.

于 2013-07-07T10:36:28.370 回答
3

C++ 标准的 n3337 版本说

形式的预处理指令 导致实现以实现定义的方式运行。该行为可能会导致翻译失败或导致翻译器或生成的程序以不合格的方式运行。任何未被实现识别的编译指示都会被忽略。#pragma pp-tokensopt new-line

我认为这允许编译器在#pragma. “翻译失败”和“翻译程序或结果程序以不合格的方式运行”都涵盖了很大范围的选项。

当然,这并不意味着允许编译器做“疯狂”的事情是明智的——它可能会“惹恼”人们,但从标准的角度来看它是完全有效的。

于 2013-07-07T10:40:50.960 回答
1

只要有文档,编译器就可以做任何事情。一个非常旧的 gcc 版本,在看到任何编译指示后,会停止编译并试图定位并启动当时存在的文本模式游戏之一。这是完全符合标准的,因为在用户指南中有一个关于它的部分。

于 2013-07-07T10:35:20.610 回答