Visual C ++警告C4800,为什么它只在return语句上触发?

时间:2010-07-12 19:31:48

标签: c++ visual-c++ compiler-warnings

我刚刚安装了Windows SDK v7.1(MSVC 10.0)并运行了我的代码(几乎)完全警告级别(W3,默认为qmake的CONFIG += warn_on)并且对警告C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)感到惊讶

在以下代码中,streamstd::istreamtokenstd::string

// in some function returning bool
return (stream >> token) // triggers warning c4800:
                         // '(void *)': forcing value to bool 'true' or 'false' (performance warning)`
// somewhere else
if( stream >> token ) // does not trigger warning c4800

这里发生了什么?我甚至不知道为什么首先触发警告。我认为第一段代码已经返回了bool

我理解这是挑剔,警告甚至不应该存在,但它是我的代码中唯一一个MSVC的/W3和gcc的-Wall -pedantic,所以我想知道:)< / p>

SMALL UPDATE :我知道警告的目的是让你知道你正在假设int-&gt; bool转换,但是 1)你为什么还要使用bool(=主要是= typedef int和2)为什么if(2)不会将2转换为真或假,我认为这是谓词的全部概念,无论是真还是假

3 个答案:

答案 0 :(得分:5)

  

这里发生了什么?我甚至不知道为什么首先触发警告。我认为第一段代码已经返回了一个bool。

  1. Streams有一个隐式转换运算符,它返回void*。 (这是safe bool idiom的一个版本。它以这种方式完成,因为void*编译的上下文少于bool,因此隐式转换可能导致不需要的上下文更少。 )[1]

  2. Streams'operator>>()返回对其左操作数的引用 - 流。这样您就可以链接输入操作:strm >> value1 >> value2执行为((strm >> value1) >> value2)

  3. 现在,当您说if( strm >> value )时,会执行strm >> value并返回一个流。为了将其放入if语句,执行隐式转换为void*,然后检查该指针是否为NULL
    这与if(ptr)没有区别,if语句隐式将其条件转换为bool,但编译器永远不会对此发出警告,因为条件不是bool是如此常见。

    使用return,这是不同的。如果要返回某种类型,通常返回的表达式应为该类型。 VC的警告很烦人,对我来说,在100次中有99次这是多余的。但剩下的1%(从来没有一个性能问题,BTW;我认为这个警告很愚蠢)让我很高兴警告就在那里。

    此警告的解决方法是

    return 0 != <expression>
    

    其中<expression>是您认为应该被视为布尔值的任何内容。

    [1] ISTR Stroustrup在某处编写operator bool()如果你搞砸了运算符会静默编译:{{1​​}}(注意ostrm >> 5;而不是>>)会编译很好,但默默地做错了。 (它将布尔值转换为整数并右移5次,然后丢弃该值。)

答案 1 :(得分:3)

案例之间的差异可能是return需要生成返回值,而if不必生成任何值,而只是分支。警告显然是必须创建一个新的数据对象,因此它由return触发,而不是由if触发。

答案 2 :(得分:0)

如果条件被评估为零或非零,则不会转换为布尔值。

即。 if(1)不生成警告,因为1不为零。 if(true)不生成警告,因为true被评估为非零。

因此,整数,指针,布尔值都被转换为“零或非零”,而不是布尔值。

但是当您尝试从具有布尔返回的函数返回整数值时,它必须假设您想要模仿该行为。这就是为什么它表示“我假设你想要将'非零变为真,零变为假',并且你得到警告。