【问题标题】:What is the scope of a pragma directive?pragma 指令的范围是什么?
【发布时间】:2011-07-02 00:14:31
【问题描述】:

pragma 指令的范围是什么?例如,如果我在另一个文件 B 中包含的头文件 A 中说 #pragma warning(disable: 4996),这是否也会禁用 B 中的所有警告?还是应该再次启用文件 A 末尾的警告?

【问题讨论】:

  • 这不是你可以自己测试的吗?
  • 无论如何不要使用“启用” - 使用“推送”/“弹出” - stackoverflow.com/q/4193476/57428
  • @Leigh:测试仅揭示某些特定版本在特定测试场景中的行为方式。这与大致了解它的工作原理大不相同。
  • @sbi:我们都知道“它是如何工作的”和“它应该如何工作”并不总是一致的。不是说你错了,我只是没有将问题理解为“#pragma supposed 如何工作”。

标签: c++ visual-studio-2008 scope header-files pragma


【解决方案1】:

直到翻译单元结束。通俗地说,TU 是源文件及其包含文件。

通常的模式是这样的:

#pragma warning (push) //save
#pragma warning (disable: xxxx)
#pragma warning (disable: yyyy)
...

//code

#pragma warning (pop) //restore prev settings

例如

//A.h
#pragma once
#pragma warning (disable: 1234)
#include "b.h"

//b.h
#pragma once
//when included after a.h 1234 will be disabled

//c.cpp
#include "a.h" //warnings 1234 from b.h is disabled

//d.cpp
#include "b.h" //warnings 1234 from b.h are not disabled
#include "a.h"

【讨论】:

  • +1,因为“end of TU”是正确的,并且给出了“push”/“pop”的强制提示。
  • +1,我仍然会提到 pragma 是特定于编译器的,虽然这是一个“常见”实现,但没有人被它束缚。特别是......模板和其他内联函数可能会对编译指示造成严重破坏。您使用模板定义的编译指示堆栈还是当前的?两种选择都不令人满意:/
  • @armen 我相信您的范围规则可能有例外。见:stackoverflow.com/questions/8107844/…
  • @ChrisMorris:我阅读了您链接到的问题和答案,但我看不出它们在任何方面都是“我的”范围规则的例外。我认为它们非常适合。
  • @Chris:任何 pragma 指令的 范围 都是从其定义/声明到翻译单元结束。但是 pragma 如何实际工作 是另一回事(C++ 标准未涵盖)。在链接的问题中,警告始终出现在翻译单元的末尾(如已接受的答案中所述),这是合乎逻辑的。 pragma 的范围不会改变。而是关于警告的范围......
【解决方案2】:

编译指示特定于使用的编译器和平台。 所以最好的办法是查看编译器的文档。

对于 IBM 编译器,例如:

可以在任意位置指定许多 pragma 指令 在源代码中指向 编译单元;其他人必须是 在任何其他指令之前指定 或源代码语句。在里面 每个单独的描述 pragma,“用法”部分描述 对编译指示的任何限制 位置。

一般情况下,如果您指定一个 pragma 指令之前的任何代码 源程序,它适用于 整个编译单元,包括任何 包含的头文件。为一个 可以出现在任何地方的指令 您的源代码,它适用于 指定的点,直到 编译单元结束。

您可以进一步限制 一个 pragma 的应用程序通过使用 互补的语用对 围绕选定部分的指令 的代码。例如,使用 #pragma 选项源和#pragma 选项 nosource 指令如下 要求只选择选定的部分 您的源代码包含在 你的编译器列表:

#pragma options source 

/*  Source code between the source and nosource pragma
    options is included in the compiler listing                */

#pragma options nosource

许多 pragma 提供“pop”或“reset” 允许您启用的子选项 并在 a 中禁用编译指示设置 基于堆栈的时尚;这些例子 在相关的编译指示中提供 描述。

一般来说,pragma 应该在其声明之后立即生效,无论它来自哪个标头,直到翻译单元的结尾。但是,有一些编译指示会影响整个程序。例如,Microsoft 特定的“链接”杂注,它将对某些库的依赖添加到翻译单元及其所有“用户”。

【讨论】:

    【解决方案3】:

    是的,它还会禁用 B 内的警告。

    翻译单元是一个 .cpp 文件,它包含的所有文件都展开成一个大文件。该 pragma 将持续到翻译单元的末尾,或者直到另一个 #pragma 警告更改设置。或者,如果您的编译器支持#pragma push 和#pragma pop,它将持续到下一个#pragma pop。

    '#pragma push' 和 '#pragma pop' 允许您创建范围。此类范围内的#pragma 警告将适用于范围的末尾。

    【讨论】:

      猜你喜欢
      • 2015-09-11
      • 2014-03-28
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-09
      • 2023-03-21
      相关资源
      最近更新 更多