如何优雅地克服无意义的 C++ 编译器警告?
Posted
技术标签:
【中文标题】如何优雅地克服无意义的 C++ 编译器警告?【英文标题】:How to overcome pointless C++ compiler warnings elegantly? 【发布时间】:2011-11-15 08:47:31 【问题描述】:这个问题不绑定任何特定的编译器警告,以下只是一个例子。
目前,当我想要一个检查内部退出条件的循环时:
while( true )
doSomething();
if( condition() )
break;
doSomethingElse();
我不能只用 Visual C++ 编写它——它会发出 C4127 conditional expression is constant
警告。尽管很明显while(true)
不可能是偶然编写的,但编译器会在我面前挥动它。
假设我想要编译时没有警告的代码。有解决方法可供我使用。
解决方法一是使用for(;;)
,但感觉很愚蠢——为什么我想要那个奇怪的东西而不是简洁优雅的惯用while(true)
? 解决方法二 是在while( true )
行之前使用#pragma warning( suppress)
,但它会添加一个比while
语句本身大两倍的巨大横幅。 解决方法三是为整个项目禁用 C4127(我在一个真实项目中看到过它),但随后所有可能有用的 C4127 实例也被禁用。
有什么优雅的方法可以消除无意义的警告吗?
【问题讨论】:
for(;;)
说forever..
g++ 在没有警告的情况下以最大可能的错误级别编译它。这个窗户是唯一的问题吗?
我同意@PrinceJohnWesley:for(;;)
是惯用的。
volatile int VeryTrue = 1; ... while(VeryTrue) ... ;
但我只是坚持使用 for(;;)。无论如何,每个用 C(++) 编写的人都必须知道这个习语。
@ern0 仅仅为了避免编译器警告,这是一个惊人且可能不可行的麻烦,因为您对编写不生成警告的 100% 等效代码有一些毫无意义的抑制。跨度>
【参考方案1】:
我会写for(;;)
,因为这是惯用的。
较新版本的 Visual C++ 并不像早期版本那样愚蠢。警告。 Visual C++ 10.0 编译使用 <windows.h>
的代码,警告级别为 4,无警告。
但是,如果您想关闭 Visual C++ 愚蠢的警告,请查看我的旧 anti-sillywarnings header,它是根据 [comp.lang.c++] 社区的输入创建的。
【讨论】:
windows.h 编译时没有警告,因为它里面塞满了#pragma warning(disable)
。
我喜欢反傻的警告标题,虽然其中一些看起来并不那个傻...
@jbat100:最让我吃惊的是,警告 4510-4513 看起来与我之前没有意识到的警告 4623-4626 非常相似。【参考方案2】:
即使没有那个警告,我也会选择for(;;)
。这不傻:它是一个没有条件的循环,这正是你想要表达的。
在我看来,这比使用 while 循环并在每次循环中测试 true 仍然为 true 更合乎逻辑(当然编译器会优化掉这个测试,因此它实际上不会影响性能)。
【讨论】:
-1 因为它只解决了 OP 给出的 example 而不是关于处理所有 无意义 警告的策略的实际问题 @Will 实际上这个问题是关于 *one 编译器中的 one 警告(C4127)。点赞。 @EJP "这个问题与任何特定的编译器警告无关,以下只是一个例子。" ... “有什么优雅的方法可以消除毫无意义的警告吗?” @我可以阅读吗,谢谢,包括你没有引用的部分。【参考方案3】:什么可以——实际可实现——更多优雅的一行:
#pragma warning ( suppress : 4127 )
(我不能使用这个,因为我还在 VS2005 上,这个 doesn't work for all warnings。)
当然,对于您的情况,for(;;)
可能是务实的方法,但总的来说
如何优雅地克服无意义的 C++ 编译器警告?
我会说disable themproject wide。 (毕竟那里毫无意义)。并且,变化
如何优雅地克服false-positve C++ 编译器警告?
我想说,单个预处理器行看起来已经很不错了。
【讨论】:
什么是单行预处理器结构? @sharptooth - 我指的是你只需要一行来表达你禁用警告的意图。在 VS2005 上,你必须摆弄几行 push/disable/pop【参考方案4】:我的理念是,如果您让编译器抑制警告,请在其中添加注释并说明原因。即使你认为这很愚蠢。 Pragma 脱颖而出并且可见。这是您代码中的一个很好的注释。
当您根据自己的想法而开始跳过 cmets 来抑制警告时,您可能会遇到潜在的麻烦。一年后编写代码的其他人可能会更改它,遇到麻烦并浪费宝贵的时间来寻找它。
顺便说一句,您正在寻找一种在没有任何一种情况下抑制警告的方法
使用编译指示 使用丑陋的代码 使用项目范围的抑制那将是一种非常隐蔽的压制方法。
如果您不喜欢 pragma 的外观,请使用
bool alwaysTrue = true; // to prevent compiler warning C4127
while (alwaysTrue)
...
【讨论】:
【参考方案5】:我使用 while(true, 1) 来抑制这个警告。
【讨论】:
【参考方案6】:做一些有趣的令牌粘贴:如果你可以交换
while(true)
为
While(true)
然后只需执行以下操作:
#define while_true for( ;; )
#define While(a) while_##a
【讨论】:
我不明白为什么。for(;;)
的行为是纯粹的约定。它应该等同于不编译的while()
。所以我把丑陋的for(;;)
藏了起来,把while
改了一点,跟原来的代码比较接近。
嗯,for(;;)
是一种广泛使用的过度设计结构,而您建议的是新引入的过度设计结构。
与这个答案相比,安装 Linux 和使用 GCC 的建议看起来更好。
投我一票死,没有人提供一个有效的例子来解决你的问题。 for 是正确的,但对某些人来说是丑陋的——我只是把它藏起来了。禁用警告可能会让你错过错误(更常见的错别字我做了一些统计数据(在 OSS 上),大约 2/3 的编码人员使用 for(;;) 而其他 1/3 用于 while(true)。for 有一个独特的 C-ish 风味,有些人可能会觉得恶心(它让我想起了数字食谱……)
我真的笑死了!谢谢@reder!让我们为这些代码增添趣味!【参考方案7】:
在许多情况下,令人满意的代码会按预期运行,但会产生大量警告。这就是为什么它们是警告而不是错误。他们惹恼你的事实是好的:警告旨在改变你的行为。你应该改过自新,而不是把它们扫到地毯下。
问题中的示例循环可以这样写:
for (; testExitCondition();)
doSomething();
在更复杂的情况下,循环计数器可以用作状态机的状态(每个动作都需要更新状态):
for (int state = stateBegin; state == stateTerminate;)
switch (state)
case stateBegin:
//elaborate setup
break;
case state_1:
doSomething_1();
break;
case state_2:
doSomething_2();
break;
case state_n:
doSomething_n();
break;
我最喜欢避免无意义的 C++ 警告的方法是使用 C# :)
诚然,这会产生大量毫无意义的 C# 警告,但没有什么是完美的。
天哪,看看反对票。证明 C++ 会损害你的幽默感。
【讨论】:
在这种情况下,答案已经在列表的底部。进一步的否决仅用于证明无幽默感的小事。我把这个问题当作一个玩笑,因为不言而喻,避免警告的方法是以不触发警告的方式编写代码。在 C# 中,可以全局或直接抑制特定成员的属性警告。人们很少使用它,因为彻底隐藏警告是个坏主意。以上是关于如何优雅地克服无意义的 C++ 编译器警告?的主要内容,如果未能解决你的问题,请参考以下文章