是否使用#pragma警告推送/弹出来临时更改警告级别的正确方法?


73

有时很难编写完全不会发出警告的C ++代码。但是,启用警告是一个好主意。因此,通常有必要禁用某些特定构造周围的警告,并在所有其他代码段中启用警告。

到目前为止,我已经看到了两种方法。

第一个是使用#pragma warning( push )#pragma warning( pop )

 #pragma warning( push )
 #pragma warning( disable: ThatWarning )
 //code with ThatWarning here
 #pragma warning( pop )

第二种是使用#pragma warning( default )

 #pragma warning( disable: ThatWarning )
 //code with ThatWarning here
 #pragma warning( default: ThatWarning )

我在第二个变体中看到的问题是它丢弃了原始警告级别-警告可能在此之前已关闭,或者其警告级别可能已更改。使用default将丢弃这些更改。

第一种方法看起来很干净。有什么问题吗?有没有更好的方法可以达到相同目的?


可移植性,但是由于它是用visual-c ++标记的,因此这对您来说可能不是问题。可悲的是,似乎没有任何解决方案能接近“令人愉悦的”。我总是采用push / pop方法。
Mark Storer

Answers:


39

第一种方法是最好的方法,IMO。我知道没有问题。

只需记住,#pragma是编译器特定的,因此不要指望它可以在每个编译器中运行:)


9
对于第一种方法,我想到了一个可能令人讨厌的问题。如果\\code with ThatWarning here头中有(第3方)标头,并且该标头中有,#pragma warning( disable: AnotherWarning)则弹出式窗口将禁用禁用功能。尽管可以说这是一件好事,但库设计人员可能正在模板中执行某些操作,从而生成警告,表明他们已确定安全。现在,在您的代码中对该模板的任何使用都会生成此警告,但会将其标记为库。根本不清楚您的代码的哪一行会触发库中的警告。
向下面对上帝

3
@DownwardFacingGod:晚回复o-rama ....但是...其他方法也会发生同样的问题...
Goz

1
正确地说,第一种方法是最好的,这没有错。2005年,Herb Sutter和Andrei Alexandrescu撰写的“ C ++编码标准101规则,准则和最佳实践”,第1版(第19页)中明确指出了这一点。
amirfg

43

这将与多个编译器(和不同版本的编译器)一起使用。

标头“推”

#if defined(__clang__)
# pragma clang diagnostic push
#endif

#if defined(_MSC_VER)
# pragma warning(push)
#endif

#if defined(YOUR_FAVORITE_COMPILER)
# pragma your compiler push warning
#endif

标头“ pop”

#if defined(__clang__)
# pragma clang diagnostic pop
#endif

#if defined(_MSC_VER)
# pragma warning(pop)
#endif

一些警告

#if defined(__clang__)
# pragma clang diagnostic ignored "-Wunused-parameter"
# pragma clang diagnostic ignored "-Wunused-variable"
#  if __has_warning("-Wnew-special-warning")
#   pragma clang diagnostic ignored "-Wnew-special-warning"
#  endif
#endif

#if defined(_MSC_VER)
# pragma warning(disable: 4100) // unreferenced formal parameter
# if _MSC_VER > _MSC_SOME_VERSION
#  pragma warning(disable: xxxx) // disable one more for special version
# endif
#endif

用法

// This code reports warnings
// ...
#include <ignore_compiler_warning/push>
#include <ignore_compiler_warning/warning_type_1>
#include <ignore_compiler_warning/warning_type_2>
#include <ignore_compiler_warning/warning_type_3>
// This code ignores warnings type_{1,2,3}
// ...
#include <ignore_compiler_warning/pop>
// Back to reporting warnings
// ...

此外,包括警卫人员可以检查是否没有双重推送/弹出/禁用警告语用说明。

更新资料


41

对于尖齿来说为时已晚,但对于那里的所有Google员工而言:

#pragma warning ( suppress: ThatWarning )
// one single line with ThatWarning

的缩写(通常从VS 2008开始,但是在VS 2005中仅用于Code Analyzer警告):

#pragma warning ( push )
#pragma warning ( disable: ThatWarning )
// one single line with ThatWarning
#pragma warning ( pop )

非常感谢!suppress在这里绝对是正确的答案,并且比push/disable/pop或优雅得多disable/enable
Nicu Stiurca '16

是vs2012中唯一的工作方式,禁用推送等..不起作用
Michel Sanches

我怀疑这是大多数编码人员想要的方法。
David A. Gray,

明智的话 丢失C前缀;只需使用数字。否则,#pragma指令将生成更多警告,并且不执行任何操作。
David A. Gray

1
尽管这是最优雅的方法(如果可以说是这样的事情),但它并不总是能按预期工作。像往常一样,细节决定了细节:#pragma warning (suppress)仅适用于下一代码,而不适用于下一个代码。自TS声明“带警告的代码”以来,我提出了这一点。
marcbf19年

13

正确的方法(虽然有点难看)

#ifdef _MSC_VER
 #pragma warning( push )
 #pragma warning( once: ThatWarning )
#endif
 //code with ThatWarning here
#ifdef _MSC_VER
 #pragma warning( pop )
#endif

13
TS希望暂时禁用某些部分代码的警告。#pragma warning(一次)将不起作用,因为它仍允许显示警告(仅一次)。我不知道支持者是否实际测试了该解决方案。(我做到了,但是没有用)。
Alex Che 2014年

“一次”与“禁用”。我相信我们谦虚的读者会发现这一点。堆栈溢出读取器显然是人类所能提供的。或者其他的东西。
Mark Storer

3

您可以在项目或文件选项中禁用特定的警告,并且该设置将被相应范围内的#pragmas用作“默认”。VS2005中的某些警告是如此的无用/烦人,以至于如果使用,这会清理输出/W4

这在“配置属性”->“ C / C ++”->“高级”下的“属性”中。


2

我对第一个变体没有问题。可能更好的方法是使用以下方法:

 #pragma warning( push )
 #pragma warning( once: ThatWarning )
 //code with ThatWarning here
 #pragma warning( pop )

这会让您知道代码中仍然有警告,但是警告消息不会那么令人讨厌。但这是口味的问题。


此警告:msdn.microsoft.com/en-us/library/1ywe7hcy(VS.80).aspx令人讨厌,即使您只看到一次;)
Goz 2010年

1
这里的问题是使编译器“将警告视为错误”会很有用。对于无法修复的错误(即某些第三方依赖性),则必须安全地禁用。
向下面对上帝

0

第一种方法允许您在本地范围内更改特定的警告设置。它首先通过压入堆栈存储所有当前警告状态,应用警告修改,然后还原(弹出)到最后警告状态。

#pragma warning(push)#pragma warning(一旦:ThatWarning)//在此使用ThatWarning编码#pragma warning(pop)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.