当将bool类型转换为int类型时,是否保证其值为0或1?

53
许多编译器似乎只保留在布尔值中的0或1,但我不确定这种方法是否总是有效。
int a = 2;
bool b = a;
int c = 3 + b; // 4 or 5?

2
关于 C++ 部分,请参见 Can I assume (bool)true == (int)1 for any C++ compiler?。关于 C 语言,请参见 Is bool a native C type? - Matthew Flaschen
2
我更感兴趣的问题措辞为“布尔表达式是否总是保证计算出0或1?”,对此,答案毫无疑问是“是”。 - bobobobo
相关:https://dev59.com/f2435IYBdhLWcg3w1juV - Palec
在更新的C版本中,有一个标准的布尔类型,它只有值0和1,就像C++一样。赋值将非零转换为1。 - gnasher729
请注意,bool转换将确保b为1。但是您仍然可以使用诸如联合,memset等黑客技术将b变成2。 - SOFe
6个回答

57

是的:

C++中(§4.5/4):

类型为bool的右值可以被转换为类型为int的右值,其中false变成0,true变成1。

在C语言中,当一个值被转换为_Bool时,它会变成0或1(§6.3.1.2/1):

当任何标量值被转换为_Bool时,如果该值与0相等,则结果为0;否则,结果为1。

当转换为int时,非常简单明了。 int可以保存0和1,因此值不会改变(§6.3.1.3)。


7
请注意,对于 C 语言,这取决于类型 _Bool。如果您使用的是 typedef enum { false, true } bool;,它就不会按照这种方式工作。 - Chris Dodd

21

好吧,并不总是这样...

const int n = 100;
bool b[n];
for (int i = 0; i < n; ++i)
{
    int x = b[i];
    if (x & ~1)
    {
        std::cout << x << ' ';
    }
}

我的系统上的输出:

28 255 34 148 92 192 119 46 165 192 119 232 26 195 119 44 255 34 96 157 192 119
8 47 78 192 119 41 78 192 119 8 250 64 2 194 205 146 124 192 73 64 4 255 34 56 2
55 34 224 255 34 148 92 192 119 80 40 190 119 255 255 255 255 41 78 192 119 66 7
8 192 119 192 73 64 240 255 34 25 74 64 192 73 64
这个看起来奇怪的输出结果的原因在于标准文档中3.9.1 §6所规定的内容:

类型为 bool 的值只能是 truefalse。如果按照国际标准描述的“未定义”的方式使用 bool 值,例如检查未初始化的自动对象的值,这可能导致它表现得既不是 true 也不是 false


3
@Sebastian: 未初始化的变量有定义行为吗? - CiscoIPPhone
4
请注意这行代码:int x = b[i],我本来期望这个随机的东西会在这里被转换成0或1。你呢? - fredoverflow
3
不是很准确,该数组只是一块未初始化的内存块,里面可以包含任何内容。如果你这样写了:bool b[n] = {0},那就不同了。无论如何,你从标准中引用的内容很有参考价值,所以因此加一分。 - hhafez
5
@Sebastian: 尝试访问未初始化的变量 未定义行为。 @FredOverflow: 你这么做了吗?我没期望有任何结果,毕竟这是未定义行为。你真的认为每次访问布尔值时都应该进行转换步骤吗?没有定义的方式可以将除 truefalse 以外的任何内容存储到布尔变量中。 - eq-
9
@Sebastian:你完全错了。如果你访问未初始化的变量的值,其他事情包括终止程序或system("rm -rf /");是被允许发生的。 - R.. GitHub STOP HELPING ICE
显示剩余8条评论

19

C/C++并不是一个语言。

在C++中,bool类型在强制转换为int时总是保证为0或1,因为第4.5/4节规定:

bool类型的rvalue可以转换为int类型的rvalue,其中false变成零,true变成一。

int c = 3 + b; // 4还是5?

c的值将会是4。


2
除了C语言,C甚至没有bool类型 :) - hhafez
2
在 C 语言中,直到 C99 版本,没有 bool 数据类型。请解除您的反对票。 - Prasoon Saurav
6
C99 定义了一个新类型 _Bool 和一个在头文件 <stdbool.h> 中的 typedef bool。如果您不包含 #include <stdbool.h>,那么您的程序无法使用 bool,但可以使用 _Bool - pmg
46
指出没有叫做C/C++的编程语言是正确但并不实用的。这个评论并没有帮助原帖作者纠正错误,因为原帖作者可能只是笔误或者不太清楚语言之间的区别。如果你熟悉C++但不熟悉C标准,请直接说明即可。 - thb
6
@thb,我不同意这个评论没有帮助。认为C++只是拥有更多特性的C语言的想法是相当普遍的。这两种语言的标准在很多方面都存在差异,这是一个重要的考虑因素。 - martinkunev

10

还有一个例子,当你离开安全船时:

  bool b = false;
  *(reinterpret_cast<char*>(&b)) = 0xFF;
  int from_bool = b;
  cout << from_bool << " is " << (b ? "true" : "false");

输出 (g++ (GCC) 4.4.7):

  255 is true

加入到FredOverflow的示例中。


3
在C90之前的版本中,如C Pre C99,没有bool类型,但是在C99/C++中,bool类型始终保证为0或1。
在C语言中,所有布尔操作都保证返回0或1,无论是否定义了bool类型。
因此,在C或C++中,无论a和b的类型如何,a && b或!a或a || b始终会返回0或1。

4
C语言确实有bool类型。从技术上讲,这个类型是_Bool,而bool是一个宏,但除非你正在使用冲突的库,否则通常并不重要。 - Matthew Flaschen
@hhafez:在C语言中,标准化的布尔类型(_Bool)比像C#这样的语言更古老。毕竟你对C语言没有太多经验吧? - eq-
C语言和C#有什么关系?我不理解你的评论。 - hhafez

1
带填充位的类型如果填充位不保持类型所期望的值,则可能表现出奇怪的行为。大多数C89实现没有在任何整数类型中使用填充位,但是C99要求实现定义这样一种类型:_Bool。当所有位都为零时读取_Bool将产生零。向_Bool写入任何非零值将设置其位为某个模式,该模式读取时将产生1。写入零将设置位为一个模式(可能是全零或非全零),该模式读取时将产生0。
除非在实现文档中另有规定,否则除了全零比特模式之外的任何比特模式,如果不可能通过存储零或非零值来产生,则为陷阱表示形式;标准对尝试读取这样的值会发生什么事情没有做出任何说明。例如:
union boolChar { _Bool b; unsigned char c; } bc;

将零存储到bc.c并读取bc.b将产生零。将零或一存储到bc.b将设置bc.c的值,如果写入,则会导致bc.b保持为零或一。将任何其他值存储到bc.c并读取bc.b将产生未定义行为。

@JohnBollinger:标准对于实现如何处理它们不需要分配含义的任何位模式没有任何要求。实现可以记录它们将如何处理这些模式的读取,但也可以记录从标准的角度来看引发未定义行为的任何其他操作。 - supercat
这更或多或少是我的观点,@supercat。标准(间接地)要求类型 _Bool 的表示具有填充位,并不意味着该类型必须提供任何陷阱表示,也不需要满足您提出的特定位模式来作为陷阱表示。标准并不限制有效表示仅限于可以作为赋值表达式的副作用存储的表示。 - John Bollinger
@JohnBollinger:从标准的角度来看,如果不是“无需表示对象类型值的对象表示”,即实现不需要附加含义的位模式,那么什么是陷阱表示?实现允许在超出标准要求的位模式上附加含义,但事实上实现记录了位模式的含义并不会阻止它成为一种“无需指定对象类型值的对象表示”。 - supercat
1
你正在比我认为的更广泛地解释陷阱表示法的定义,这可能不是预期或必要的。请考虑标准的规定,对于带符号整数,表示具有符号位为1且所有其他位为0的表示是否为陷阱表示法是由实现定义的。就标准而言,该模式不一定表示一个值,但也不一定是陷阱表示法。 “不需要表示一个值”的措辞有点费解,但应从实现的角度进行解释。 - John Bollinger
然而,从另一个角度来看这个整体问题,标准允许为 _Bool 类型的对象分配不同于 0 和 1 的值。它要求生成的 _Bool 值与 0 或 1 相等,但它并不限制生成的表示仅限于分配 0 或 1 所产生的表示,也不要求分配 0 所产生的表示是全零位。因此,即使根据您自己对“陷阱表示”的解释,您的声明似乎也得不到标准的支持。 - John Bollinger
显示剩余6条评论

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