9

<windows.h>头带有自己的BOOL类型。看看实现,它似乎FALSE只是一个宏0TRUE只是一个宏1,但我不确定这是指定的。

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

bool a = static_cast<bool>(x);

bool b = x ? true : false;

bool c = (x == TRUE);

bool d = (x != FALSE);

bool e = !!x;

// ...
4

5 回答 5

8

不需要任何显式转换:

BOOL x = some_value;
bool b = x;

对于 的值和任何非零值,将数值类型隐式转换为bool收益。false0true

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

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

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

但是根据这个在线 Visual C++ 编译器,VC++ 确实会产生一个警告:

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

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

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

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

如果您有避免编译器警告的附加要求,那么这将成为更多关于 Visual C++ 而不是 C++ 语言的问题。也可能有一些方法可以在不改变来源的情况下抑制某些警告——尽管当它们真正有意义时可能会丢失这些相同的警告。在评论中,Dieter Lücking 建议:

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

但这看起来仍然需要修改源。也许有一些等效的东西没有。

还有一件事:因为BOOL真的是 type int,所以这个建议的解决方案:

bool c = (x == TRUE);

不等于其他。任何非零int都被视为真,但只有1等于。例如,上面将设置为if —— 而仍将其视为真实条件。永远不要将布尔值与or进行比较。(将它们与or比较更安全,但仍然没有必要;这就是操作员的目的。)TRUEcfalsex == 2if (x)trueTRUEfalseFALSE!

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

最后,我责怪微软为BOOL已经拥有完美表现的内置类型的语言定义了一个bool类型。实际上这不太公平。它用于需要从 C 和 C++ 访问的 API。微软的定义BOOL可能可以追溯到他们的 C 实现,这在某种程度上是有道理的——至少在微软仍然不支持的 C99 之前。(我不知道 Microsoft 的 C 编译器是否支持_Bool. 即使支持,也与_Bool有一些语义差异int,并且更改 的定义BOOL可能会破坏某些代码——尤其是使用. 的代码GetMessage。)

于 2013-08-29T20:00:12.070 回答
0

很难说 win32 程序员如何做到这一点,但恕我直言,应该通过以下方式完成:

bool c = (X == TRUE);

或者

bool d = (x != FALSE);

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

有一天 TRUE 可能变成 0 和 FALSE 1 ;)

于 2013-08-29T20:08:44.383 回答
0

没有安全的方法可以做到这一点,因为 Win32BOOL两个以上的值

于 2013-08-29T20:16:31.053 回答
0

我使用宏:

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

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

已编辑: 评论者质疑我在宏名称中使用下划线。为了解决这个问题,这里有一个新版本,它仍然是通用的,并且仍然使用相同的名称_bool,但是是合规的,根据this

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

using namespace MyBool;
于 2013-08-30T05:35:32.450 回答
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选项的性能警告似乎令人震惊,但我们已经排除了它不太优雅。)

dand表达式清楚地表达了意图,b并清楚地表明这里发生的事情比直接赋值要多。

于 2016-11-15T22:08:09.460 回答