C++ visualc&x2B+;警告C4800,为什么它只在返回语句时触发?

C++ visualc&x2B+;警告C4800,为什么它只在返回语句时触发?,c++,visual-c++,compiler-warnings,C++,Visual C++,Compiler Warnings,我刚刚安装了Windows SDK v7.1(MSVC 10.0)并运行了(几乎)完全警告级别的代码(W3,默认为qmake的CONFIG+=warn\u on),对警告C4800:'type':强制值bool'true'或'false'(性能警告) 在下面的代码中,stream是一个std::istream,token是一个std::string // in some function returning bool return (stream >> token) // trigg

我刚刚安装了Windows SDK v7.1(MSVC 10.0)并运行了(几乎)完全警告级别的代码(W3,默认为qmake的
CONFIG+=warn\u on
),对警告
C4800:'type':强制值bool'true'或'false'(性能警告)

在下面的代码中,
stream
是一个
std::istream
token
是一个
std::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
之间的唯一警告,所以我想知道:)


小更新:我知道这个警告的目的是让你知道你正在假设int->bool转换,但是1)为什么你仍然使用bool(=
typedef int
大部分)和2)为什么
如果(2)
不将
2
转换为true或false,我认为这就是谓词的全部想法,是真是假。

这两种情况之间的区别可能是
返回
需要生成返回值,而
如果
不需要生成任何值,只需分支即可。警告显然是必须创建一个新的数据对象,因此它由
return
触发,而不是由
if

触发,如果条件被评估为零或非零,而不是转换为布尔值

i、 e.如果(1)没有生成警告,因为1不是零。 if(true)不会生成警告,因为true的计算结果为非零

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

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

这里发生了什么?我甚至不明白为什么会触发警告。我想第一段代码已经返回了bool

  • 流有一个隐式转换运算符,它返回一个
    void*
    (这是的一个版本。之所以这样做,是因为
    void*
    编译的上下文少于
    bool
    ,因此隐式转换可能进入不需要的上下文就更少了。)[1]

  • Streams的
    运算符>>()
    返回对其左操作数(流)的引用。这样您就可以链接输入操作:
    strm>>value1>>value2
    作为
    执行((strm>>value1)>>value2)

  • 现在,当您说
    if(strm>>value)
    时,将执行
    strm>>value
    ,并返回一个流。为了将其放入
    if
    语句中,将执行到
    void*
    的隐式转换,然后检查该指针是否为
    NULL

    这与
    if(ptr)
    没有区别,
    if
    语句隐式地将其条件转换为
    bool
    ,但编译器永远不会对此发出警告,因为这种条件不是
    bool
    非常常见

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

    此警告的解决方法是

    return 0 != <expression>
    
    返回0!=
    
    其中,
    是您认为应该被视为布尔值的值


    [1] ISTR Stroustrup在某个地方写到,如果你把操作符搞糟了,一个
    操作符bool()
    会自动编译:
    ostrm>>5;
    (注意
    >
    而不是
    ,这是不正确的。§6.4/4规定(除了
    开关
    )一个条件被转换为bool。如果
    (例如)如果该值为
    true
    @Gman,则执行其语句:标准规定了行为,而不是编译器必须遵循的确切代码。转换为布尔值,然后根据该值进行分支(在许多体系结构中为整数类型),在语义上等同于不在零/非零上转换和分支。脚注5)中注释的§1.9/1中的标准有时称为“仿佛”规则,因为一个实现可以自由地忽略这个国际标准的任何要求,只要结果是符合要求的,就可以从程序的可观察行为来确定。@David:是的,但答案说它们绝对不会被视为布尔值(而是0或非0),这是完全错误的。它们总是被视为布尔值。(只是转换可能是通过false为0,true为非0来完成的。但条件本身是布尔值。)因此基本上编译器会说:“嘿,返回表达式的类型与返回类型不匹配,请确保它显式。"?感谢您的充分解释,但它仍然表明msvc不符合
    if
    的标准,它应该将条件转换为
    bool
    @ruben:警告与合规性无关。
    if
    的条件当然会转换为
    bool
    ,但警告并非严格意义上的转换rsion,它是关于转换以生成一个“真实”值(与“临时”值相反)。+1但要挑剔,我相信这是一个void*转换,而不是const void*。请参见27.4.4。@Neil:你说得对,谢谢。