pragma指令的范围是什么?

fre*_*low 20 c++ scope pragma header-files visual-studio-2008

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

Arm*_*yan 19

直到翻译单元结束.非正式地,TU是包含其文件的源文件.

通常的模式是这样的:

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

//code

#pragma warning (pop) //restore prev settings
Run Code Online (Sandbox Code Playgroud)

例如

//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"
Run Code Online (Sandbox Code Playgroud)

  • +1,我仍然会提到`pragma`是特定于编译器的,虽然这是一个"常见"实现,但没有一个是有限的.特别是......模板和其他内联函数可能会对pragma造成严重破坏.您是使用模板定义的pragma堆栈还是当前的堆栈?这两种选择都不令人满意:/ (3认同)
  • @Chris:任何pragma指令的***范围***都是从其定义/声明到翻译单元结束.但是pragma实际***如何工作***是另一回事(C++标准未涵盖).在链接的问题中,警告始终发生在翻译单元的末尾(如接受的答案中所述)是合乎逻辑的.pragma的范围不会改变.这更像是警告的范围...... (2认同)

小智 8

Pragma特定于正在使用的编译器和平台.所以最好的办法是查看编译器的文档.

对于IBM编译器,例如:

可以在编译单元的源代码中的任何点指定许多pragma伪指令; 必须在任何其他指令或源代码语句之前指定其他语句.在每个pragma的单独描述中,"Usage"部分描述了对pragma放置的任何约束.

通常,如果在源程序中的任何代码之前指定pragma伪指令,它将应用于整个编译单元,包括所包含的任何头文件.对于可以出现在源代码中的任何位置的指令,它从指定的位置开始应用,直到编译单元结束.

您可以通过在选定的代码段周围使用互补的pragma指令对来进一步限制pragma应用程序的范围.例如,如下所示,使用#pragma options source和#pragma options nosource指令请求只将源代码的选定部分包含在编译器列表中:

#pragma options source 

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

#pragma options nosource
Run Code Online (Sandbox Code Playgroud)

许多编译指示提供"弹出"或"重置"子选项,允许您以基于堆栈的方式启用和禁用编译指示设置; 这些示例在相关的编译指示描述中提供.

一般来说,pragma在声明之后应该有效,无论它来自哪个标题,直到翻译单元结束.但是,有一些pragma会影响整个程序.例如,特定于Microsoft的"链接"编译指示,它将某些库的依赖性添加到翻译单元及其所有"用户".