为什么与 bool 的比较在 C11 中不转换为 bool?

Why doesn't comparison with bool convert to bool in C11?

给定以下 C11 代码:

int a = 1234;

bool b = (bool)a; // equivalent to (a != 0) or (a != false) which evaluates to 1 or true

if (a) // equivalent to if(a != 0) or if (a != false) which evaluates to 1 or true
  printf("a\n");

if (a == (bool)true) // should be equivalent to if(!(a == false)) or if (a != false)
  printf("a == (bool)true\n");

我知道 true 是 #define true 1bool 显然不是普通的整数类型,因为像 (bool)0.1 这样的东西的计算结果为 1,而转换为 int 将导致 0。

1) 为什么 true 没有被定义为 (bool)1?这将允许编译器至少输出警告。

2) 为什么我的示例中的整数没有转换为 bool,使得 a == (bool)true 的计算结果为 (bool)a == (bool)true,这实际上是真的?

根据评论总结:

_Bool 实际上是 "just" 另一种无符号整数类型,如果值不等于 0 ("false").

因为它是无符号整数,所以适用整数提升规则。 即使 true 被定义为 (bool)1,比较 a == true 也会导致实际比较 1234 == 1,它总是 false.

I understand that true is #define true 1 but a bool clearly is not an ordinary integral type because something like (bool)0.1 evaluates to 1 while a cast to int would result in 0.

bool(其实是_Boolbool是扩展为_Bool的宏)是整型。它确实有一个不与任何其他类型共享的有点不寻常的特性:将任何非零值转换为 _Bool 会产生 1.

请注意,产生逻辑布尔值的运算符仍会产生值为 01int 结果。由于隐式转换,这通常不是问题。

1) Why wasn't true defined as (bool)1? This would allow the compiler to at least output a warning.

编译器可以随时生成警告。在与 truefalse 进行比较时发出警告是个好主意。

2) Why is the integer in my example not converted into a bool such that a == true would evaluate to (bool)a == true which actually would be true?

a == true 必须先将其操作数转换为相同类型,然后才能比较它们。这是通过 通常的算术转换 完成的。 N1570 第 6.3.1.8 节中描述了规则(相当复杂)。一个非常快速和不精确的总结是,较窄类型的操作数(较小的整数转换等级)被转换为另一个操作数的类型。例如,当您比较类型 intlong 的表达式时,int 操作数被提升为 long_Bool 是最窄的整数类型,所以它总是在比较中被提升,除非它正在与另一个 _Bool 值进行比较。

仅仅为了 _Bool 改变这些规则会让人感到困惑,而且它真的不会给你带来太多好处。

底线:不要将值与 falsetrue 进行比较。不要写:

if (a == true)

随便写:

if (a)

如果这就是你的意思。同样,不要写:

if (a == false)

随便写

if (!a)

Why doesn't comparison with bool convert to bool in C11?

_Bool 是最低等级,相等运算符 == 指定其 _Bool 操作数提升为 int


The rank of _Bool shall be less than the rank of all other standard integer types. C11 §6.3.1.1 1

(Equality operators) If both of the operands have arithmetic type, the usual arithmetic conversions are performed. §6.5.9 4

(usual arithmetic conversions) ... the integer promotions are performed on both operands §6.3.1.8 1

(integer promotions) If an int can represent all values of the original type ... the value is converted to an int ... §6.3.1.1 2


OP 的代码示例没有 "comparison with bool".

// int compared to int: false since a == 1234 and that is not equal 1
if (a == true)  

本来可以

// int compared to _Bool: false since a == 1234 and that is not equal to 0 or 1
if (a == b) 

对于int == _Boolint == shortint == signed char,同样的事情发生。较低级别的操作数提升为 int.


1) Why wasn't true defined as (bool)1? This would allow the compiler to at least output a warning.

为什么?多年前的标准委员会决定。将 true 视为 (int)1 而不是 (_Bool)1 肯定会在引入 _Bool 时对现有代码的影响较小。 (C99)。这与其他子 int 常量一致,例如 SHRT_MAX,通常是 int,而不是 short。在任何情况下,在大多数情况下,无论如何都会在进一步处理之前升级到 int/unsigned - 就像在这个比较案例中一样。

不需要进一步 (_Bool)1 来允许编译器提供警告。可以制作一个编译器,使用各种分析工具提供警告。作为 (_Bool)1,它会简化编译器提供此类警告的事情。

2) Why is the integer in my example not converted into a bool such that a == true would evaluate to (bool)a == true which actually would be true?

因为 true 是一个 (int)1,而 a == true,两个操作数都是 int_Bool 不适用于此处。

2) [OP Updated] Why is the integer in my example not converted into a bool such that a == true would evaluate to (bool)a == true which actually would be true?

答案的顶部解决了这个问题:trueint 中,因此 (bool)a 在比较之前被提升为 int 作为 int排名高于 _Bool.