我如何习惯性地将BOOL转换为bool?

时间:2013-08-29 19:55:07

标签: c++ windows winapi boolean type-conversion

<windows.h>标头带有自己的BOOL类型。对实现进行窥视,似乎FALSE只是0的一个宏,TRUE只是1的一个宏,但我不确定是否已指定。

BOOL转换为bool的惯用方法是什么?我可以想象很多可能的方法:

bool a = static_cast<bool>(x);

bool b = x ? true : false;

bool c = (x == TRUE);

bool d = (x != FALSE);

bool e = !!x;

// ...

5 个答案:

答案 0 :(得分:6)

无需任何明确的转换:

BOOL x = some_value;
bool b = x;

将数值类型隐式转换为bool会使false的值为0,而true则会产生任何非零值。

顺便提一下,您已告诉我们<windows.h>如何定义FALSETRUE。它如何定义BOOL? (根据您的评论,typedef int BOOL;

但有些编译器可能会警告这种隐式转换,即使它是完全有效的代码。编译器可以随意警告他们喜欢的任何内容,包括用于编写代码的丑陋字体。例如,g ++不会抱怨转换,即使是:

g++ -std=c++11 -pedantic -Wall -Wextra ...

但根据this online Visual C++ compiler,VC ++确实会产生警告:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)

即使使用static_cast,它仍会产生警告。

您可以使用!!xx ? true : false来避免警告。但我不确定治愈方法是否比疾病更好。

这样做的简单而正确的方法就是分配值并依靠隐式转换来做正确的事情(它会)。

如果您还需要避免编译器警告,那么这就变成了一个关于Visual C ++而不是C ++语言的问题。可能还有某种方法可以在不改变来源的情况下禁止某些警告 - 尽管当它们真正有意义时可能会失去同样的警告。在评论中,DieterLücking建议:

#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)

但看起来仍然需要修改源代码。也许有一些东西不相同。

还有一件事:因为BOOL实际上是int类型,所以提出了这个解决方案:

bool c = (x == TRUE);

不等同于其他人。任何非零int都被视为true,但只有值1 等于TRUE。如果c,上述内容会将false设置为x == 2,而if (x)仍会将其视为真实条件。切勿将相等的布尔值与trueTRUE进行比较。 (将它们与falseFALSE进行比较更安全,但仍然没有必要;这就是!运算符的用途。)

这一切都假定如果你有BOOL类型的值,你只关心它是假的还是真的(零或非零)。不幸的是,情况可能并非总是如此。正如Ben Voight's answer所指出的,Microsoft的API包含至少一个函数GetMessage,该函数返回一个简单布尔值的BOOL结果。在这种可怕的情况下,如果您需要区分多个非零值,则从BOOL转换为bool是不合适的。

最终,我责怪微软为一种已经表现得非常好的内置BOOL类型的语言定义类型bool实际上这并不公平;它用在需要从C和C ++访问的API中。微软对BOOL的定义可能会回到他们的C实现,它有一定意义 - 至少在C99之前,微软仍然不支持。 (我不知道Microsoft的C编译器是否支持_Bool。即使它确实如此,_Boolint有一些语义差异,更改BOOL的定义可能会破坏一些代码 - 特别是使用GetMessage的代码。)

答案 1 :(得分:1)

我使用宏:

#define _bool(b) (!!(b)) 

IMO,让我的代码更具可读性。

<强>编辑: 一位评论者质疑我在宏名中使用下划线。为了解决这个问题,这里是一个新版本,它仍然是通用的,仍然使用相同的名称_bool,但符合this的要求。

namespace MyBool 
{
    template<typename T> inline bool _bool(const T b) 
    {
        return !!b;
    }
}

using namespace MyBool;

答案 2 :(得分:0)

很难说win32程序员会怎么做,但恕我直言应该通过以下方式完成:

bool c = (X == TRUE);

bool d = (x != FALSE);

我认为继续宏(或任何其他预定义的东西)是一种不好的做法 恒定。

一天TRUE可能变为0而FALSE 1;)

答案 3 :(得分:0)

没有安全的方法,因为Win32 BOOLmore than two values

答案 4 :(得分:0)

这是一个意见问题,但我认为对各种选择都有客观的论据。

最好的选择是:

bool d = (x != FALSE);

这使得读者非常清楚这一意图,并不依赖于隐含的转换,并且明确表示还有比简单的任务更多的事情。

第二个最佳选择是:

bool b = x ? true : false;

但是,对于随意的读者来说,这看起来像是重言式。

我尽量避免在分配中进行隐式转换,因为获取错误的转换是一个令人惊讶的错误来源。即使我知道隐式转换会做正确的事情,我倾向于明确地做,这可能对将来阅读代码的人有所帮助。明确还允许您保持启用转换警告,以便捕获您不知道自己(ab)使用的其他隐式转换。

替代品都有更严重的缺点。

bool a = static_cast<bool>(x);

这就像把一个方形钉子敲成一个圆孔。编写一个自然返回正确类型的表达式会更优雅。

bool c = (x == TRUE);

TRUE进行比较通常是一个坏主意,因为其他非零值会转换为false,这几乎肯定是错误。

bool e = !!x;

与明确表达您的意思的替代方案相比太聪明了。 (我过去曾经这样做过。)

bool f = x;

MSVC ++对纯粹隐式转换发出的性能警告似乎是公平的。编译器必须生成额外的代码才能将int转换为bool。裸露的任务对这项额外的工作几乎没有任何线索。如果它处于紧密循环中,你可能会在意。 (当然,static_cast选项上的效果警告似乎很令人震惊,但我们已经将其排除在优势之外。)

db表达清楚地表达了意图,并且显而易见的是,这里的内容比直接分配更明显。