什么时候是布尔而不是布尔(编译器警告 C4800)

Posted

技术标签:

【中文标题】什么时候是布尔而不是布尔(编译器警告 C4800)【英文标题】:When is a bool not a bool (compiler warning C4800) 【发布时间】:2012-06-27 02:18:23 【问题描述】:

考虑这是在 MS Visual Studio 2005(可能还有其他)中编译的:

CPoint point1( 1, 2 );
CPoint point2( 3, 4 );
const bool point1And2Identical( point1 == point2 );            // C4800 warning
const bool point1And2TheSame( ( point1 == point2 ) == TRUE );  // no warning

什么...? MSVC 编译器是不是脑死了?据我所知,TRUE 是#defined 为 1,没有任何类型信息。那么这两条线之间有什么不同呢?在这两种情况下,括号内的表达式的类型肯定是相同的吗? [这部分问题现在在下面的 cmets 中得到了令人满意的回答]

就个人而言,我认为通过使用 == TRUE 选项来避免警告是丑陋的(尽管比 != 0 选项更丑陋,尽管更严格正确),最好使用 #pragma warning( disable: 4800 ) 暗示“我的代码很好,编译器是个混蛋”。同意吗?

注意 - 我已经看到关于 C4800 的各种讨论,谈论将整数分配给布尔值,或者将带有大薯条(保持洋葱)的汉堡组合投射到布尔值,并想知道为什么会有奇怪的结果。对于一个看起来简单得多的问题,我找不到明确的答案……总的来说,这可能只是 C4800 的亮点。

【问题讨论】:

查找与CPoint类相关的operator==的声明。 不——你找它 :-) 我根本找不到任何魔法——operator == 返回一个 BOOL,它是一个 int 的 typedef。据我所知,int == TRUE 仍然是一个 int。 在内置类型上,== 生成 bool,而不是 BOOL 如果你肯定想让 operator == 返回 BOOL,那么你也应该将 point1And2Idential 声明为 BOOL 以避免警告。 True - 如果您对整数或双精度数而不是 CPoints 执行相同操作,则任何一种形式都不会出现警告。我想 == 在内置类型上返回一个布尔值,因为做任何其他事情都会违反 C++ 标准?这清楚地说明了发生了什么......但我仍然认为我更喜欢 #pragma 解决方案,或者如果可能的话,从 const bool 赋值构造更改为 if (...)。 【参考方案1】:

Have a look at this

通常,此消息是由将 int 变量分配给 bool 变量引起的

TRUEBOOL 是整数,而不是布尔值。

您也可以检查(point1 == point2) != 0或使用!!(point1 == point2)

编辑

!!操作只是将结果转换为布尔值,并且由于它是双重否定的,因此您将收到相同的结果。

here 和here 之前都对此进行过讨论。

【讨论】:

你知道...我有点喜欢 !!(point1 == point2) 作为替代方案。这是一件很奇怪的事情,就像#pragma 一样。任何随后试图删除 !!会收到警告,也会面临同样的困境。但我仍然认为#pragma 说得更明确 - 很有可能有人会假设!是一个错字,并将其更改为单个 !,或将 == 更改为 !=。虽然有创造性的答案:-) 这回答了您关于 C4800 警告的问题以及它为什么会出现在您的情况中。至于你是使用宏还是 !!或 != 0 来抑制这些警告完全取决于您的个人喜好。【参考方案2】:

实际上你不会使用 ASSERT(point1 == point2) 吗? CPoint 类上的运算符显式重载,如果点相等则返回 nonzero,否则返回 0。著名的 ASSERT 宏让我很生气,但是如果你看看 ASSERT 宏是如何扩展的,它几乎类似于在代码中添加上面的 == TRUE。看看this link on msdn。请注意示例代码明确声明不直接对两个 CPoint 对象使用相等运算符。我同意您的代码看起来最正确,但这就是我们喜欢 C++ 的原因。呃……

【讨论】:

是和不是。我想为 const bool 赋值的原因是为了随后在我测试 if (point1And2TheSame && point3And4TheSame && !point5And5TheSame... ) 和类似的(几个)其他地方使用。所以 ASSERT() 是不合适的。它在 RELEASE 构建中也消失了。 同意 ASSERT 不参与发布版本。我同意使用描述原因的注释禁用代码中的警告是这种情况下的最佳解决方案。我确实喜欢 Matt Millwoods 对 !!(point1 == point2) 的建议,但我也同意它并没有真正阐明语法背后的推理。祝你好运!【参考方案3】:

现在让我满意的答案是这样的:

在内置类型上,运算符 == 返回 bool(根据 C++ 标准的要求)。

对于 CPoint 和许多其他 Microsoft 类型,operator == 返回 Microsoft 的 BOOL,该类型定义为 int。

所以...第一个 const bool 分配行尝试将 int 分配给 const bool,导致 C4800。

第二个 const bool 赋值行将 int 与值 TRUE 进行比较,该值的类型定义为 1(编译器假定为 int),因此 int == int 比较的结果是 bool。这会在没有警告的情况下分配给 const bool。

至于屏幕上看起来最好的东西,#pragma 是丑陋且不必要的。如果你不喜欢多余的 != 0 的外观,那么试试这个:

#define ISTRUE( x )  ( (x) != 0 )

const bool point1And3Identical( ISTRUE( point1 == point2 ) );    // no warning

从语义和句法上看,这似乎是美化代码的更好方法。您可以悄悄地将 ISTRUE() 的#define 放入头文件中,使其看起来更漂亮。

【讨论】:

以上是关于什么时候是布尔而不是布尔(编译器警告 C4800)的主要内容,如果未能解决你的问题,请参考以下文章

重构MFC,你使用BOOL还是bool [重复]

Objective C 布尔数组

“布尔”和“布尔”有啥区别?

Pandas:更改通过列中的布尔索引选择的值而不会收到警告

代码中存在数据类型错误,其中类型是布尔值而不是整数

大摇大摆的布尔值作为字符串而不是 NestJS 中的布尔值发送