在C/C++中将整数转换为布尔值

51
我知道在C和C++中,将bool转换为int时,(int)true == 1(int)false == 0。我想知道反向转换的情况...
在下面的代码中,在使用Visual Studio 2013和Keil µVision 5编译的.c文件中,所有以下断言都成立。请注意,(bool)2 == true
C和C++标准对于将非零、非一的整数转换为bool有何规定?这种行为是否被详细说明?请包含引文。
#include <stdbool.h>
#include <assert.h>

void TestBoolCast(void)
{
    int i0 = 0, i1 = 1, i2 = 2;

    assert((bool)i0 == false);
    assert((bool)i1 == true);
    assert((bool)i2 == true);

    assert(!!i0 == false);
    assert(!!i1 == true);
    assert(!!i2 == true);
}

不是Can I assume (bool)true == (int)1 for any C++ compiler?的副本:

  1. 反向转换(int --> bool)。
  2. 在那里没有讨论非零、非一的值。

7
所有非零整数应转换为true。我没有规范,因此我不会发布答案。 - yizzlez
1
在C/C++中,任何非零值都是真,而0则为假。因此,2确实是真的。(2!= 0)== true。 - ydobonebi
2
@SergeyK。你真的读了这个问题吗? - emlai
1
使用(n!= 0)而不是(bool n)始终是安全的。 - Pouya Tehrani
@Olaf(关于在MSFT世界中True == -1)在C和C++的世界中,这是非标准的。然而,这个想法让我觉得很有趣。在QBASIC(用于DOS)中,“Not”关键字是一个位NOT运算符。实际上,在现代VB.NET中,“x And y”等同于C中的“x&y”;所有传统的布尔运算符在该语言中都具有位运算行为。有了这些信息以及在二进制补码系统中~0 == -1的事实,我对True == -1毫不惊讶;这就像在C中使用#define FALSE 0后跟着#define TRUE ~(FALSE)一样。 - user539810
显示剩余6条评论
3个回答

79

基本类型的0值(1)(2)映射为false

其他值映射为true

这个约定是通过C语言的流控制语句在原始C中建立的;当时C没有布尔类型。


认为false表示失败是一个常见的错误,但特别地从main返回值,false表示成功。我曾经看到许多次这样做得不对,包括D语言的Windows启动代码(当像Walter Bright和Andrei Alexandrescu这样的人都弄错了,那么你很容易就会犯错),因此请注意风险。


对于内置类型,无需将其转换为bool,因为转换是隐式的。然而,Visual C++(Microsoft的C++编译器)有时会发出性能警告(!) ,这是纯粹愚蠢的警告。一个强制转换并不足以使它消失,但是通过双重否定进行转换,即return!!x,效果非常好。可以将!!解释为“转换为bool”运算符,就像-->可以解释为“指向”的运算符一样。对于那些非常注重运算符符号的可读性的人。


1) C++14 §4.12/1:“零值、空指针值或空成员指针值转换为false;任何其他值转换为true。对于直接初始化(8.5),类型为std::nullptr_t的prvalue可以转换为类型为bool的prvalue;结果值为false。”

2) C99和C11 §6.3.1.2/1:“当将任何标量值转换为_Bool类型时,如果该值与0相等,则结果为0;否则,结果为1。”

18
我不认为main函数返回"false"代表成功。 main函数返回的是int类型,而不是bool类型,并且有不同的成功/失败惯例。(Unix系统调用使用第三种映射方式。) - Steve Summit
你能引用标准中确认你第一部分的章节吗? - cp.engr
2
@cp.engr:我猜你没有标准或草案的副本。最好获取一份,例如C++14的N3936(最新草案)。当你查看它时,你会发现§4.12规定:“零值、空指针值或空成员指针值转换为false;任何其他值都转换为true。对于直接初始化(8.5),std::nullptr_t类型的prvalue可以转换为bool类型的prvalue;结果值为false。”希望这不是作业?在文档中找到自己的路非常重要,包括神圣的标准™。 - Cheers and hth. - Alf
2
@cp.engr:哦。很抱歉,我没有最新的C标准。在C99中,在§6.3.1.2/1中指定:“当任何标量值被转换为_Bool时,如果该值与0相等,则结果为0;否则,结果为1”。 - Cheers and hth. - Alf
@Cheersandhth.-Alf,感谢您提供的引用。C++14的引用是否适用于所有旧版本的C++?C标准的引用是否适用于C89、C90? - cp.engr
显示剩余4条评论

24
以下引用了C11标准(最终草案)。
当任何标量值被转换为_Bool时,如果该值与0相等,则结果为0;否则,结果为1。这是来自6.3.1.2:的规定。 bool(由stdbool.h映射到C内部名称_Bool)本身是一种无符号整数类型
...类型_Bool和对应于标准有符号整数类型的无符号整数类型是标准的无符号整数类型。
根据6.2.5p2的规定:
声明为_Bool类型的对象足够大,可以存储值0和1。
据我所知,这些定义在语义上与C++完全相同 - 仅内置名称有轻微差异。C++使用bool,而C使用_Bool
请注意,C不像C++那样使用术语rvalues。但是,在C中,指针是标量,因此将指针分配给_Bool的行为与C++相同。

2
从C++03中:“算术、枚举、指针或成员指针类型的rvalue可以转换为bool类型的rvalue。零值、空指针值或空成员指针值被转换为false;任何其他值都被转换为true。”我相信这个问题是一个重复的问题。 - Michael Burr
2
关于“据我所知,C和C++之间这些定义是相同的”的说法并不完全正确。在C++中,bool是一种内置类型,而不是宏,也没有类似于_Bool的东西。 - Cheers and hth. - Alf
1
@Cheersandhth.-Alf:是的,我认为我已经很清楚地说明了“由stdbool.h映射到C的内部名称_Bool”。这只是名称:C:_Boolbool是映射到_Bool的宏),C ++:bool。原因是向后兼容性,因为许多代码都有自己的bool别名/ #define / enum。该类型仅在标准中添加得太晚了。 - too honest for this site
1
@cp.engr:我同意你的问题与关闭链接中的问题不是重复的。我可能不应该在我的评论中提到任何关于重复的事情-对此很抱歉。这真的对我来说并不重要,无论它是否是重复的,它都是一个合法的问题,有合法的答案。最重要的是,您应该能够依靠直觉行为(0转换为false,非零转换为true)。 - Michael Burr
1
需要注意的一个陷阱是,一些代码库(特别是 C99 之前的代码库)可能会使用 typedef char booltypedef int bool 来代替使用 stdbool.h。 - M.M
显示剩余4条评论

1

有一种老派的“马克思主义”方法可以将int转换为bool,而不会出现Microsoft的cl编译器的C4800警告 - 就是使用否定的否定。

int  i  = 0;
bool bi = !!i;

int  j  = 1;
bool bj = !!j;

1
这不是强制类型转换,也没有回答问题。 - cp.engr
@Mykyta Kozlov,这个转换方法的关键字是什么?我只想找一个参考。 - AJ_Nur
在 C/C++ 中,运算符 ! 被称为逻辑非运算符。在上面的例子中,它被应用了两次。 - Mykyta Kozlov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接