为什么与 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 1
但 bool
显然不是普通的整数类型,因为像 (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
(其实是_Bool
;bool
是扩展为_Bool
的宏)是整型。它确实有一个不与任何其他类型共享的有点不寻常的特性:将任何非零值转换为 _Bool
会产生 1
.
请注意,产生逻辑布尔值的运算符仍会产生值为 0
或 1
的 int
结果。由于隐式转换,这通常不是问题。
1) Why wasn't true
defined as (bool)1
? This would allow the compiler
to at least output a warning.
编译器可以随时生成警告。在与 true
或 false
进行比较时发出警告是个好主意。
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 节中描述了规则(相当复杂)。一个非常快速和不精确的总结是,较窄类型的操作数(较小的整数转换等级)被转换为另一个操作数的类型。例如,当您比较类型 int
和 long
的表达式时,int
操作数被提升为 long
。 _Bool
是最窄的整数类型,所以它总是在比较中被提升,除非它正在与另一个 _Bool
值进行比较。
仅仅为了 _Bool
改变这些规则会让人感到困惑,而且它真的不会给你带来太多好处。
底线:不要将值与 false
或 true
进行比较。不要写:
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 == _Bool
、int == short
、int == 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?
答案的顶部解决了这个问题:true
在 int
中,因此 (bool)a
在比较之前被提升为 int
作为 int
排名高于 _Bool
.
给定以下 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 1
但 bool
显然不是普通的整数类型,因为像 (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 abool
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
(其实是_Bool
;bool
是扩展为_Bool
的宏)是整型。它确实有一个不与任何其他类型共享的有点不寻常的特性:将任何非零值转换为 _Bool
会产生 1
.
请注意,产生逻辑布尔值的运算符仍会产生值为 0
或 1
的 int
结果。由于隐式转换,这通常不是问题。
1) Why wasn't
true
defined as(bool)1
? This would allow the compiler to at least output a warning.
编译器可以随时生成警告。在与 true
或 false
进行比较时发出警告是个好主意。
2) Why is the integer in my example not converted into a
bool
such thata == true
would evaluate to(bool)a == true
which actually would be true?
a == true
必须先将其操作数转换为相同类型,然后才能比较它们。这是通过 通常的算术转换 完成的。 N1570 第 6.3.1.8 节中描述了规则(相当复杂)。一个非常快速和不精确的总结是,较窄类型的操作数(较小的整数转换等级)被转换为另一个操作数的类型。例如,当您比较类型 int
和 long
的表达式时,int
操作数被提升为 long
。 _Bool
是最窄的整数类型,所以它总是在比较中被提升,除非它正在与另一个 _Bool
值进行比较。
仅仅为了 _Bool
改变这些规则会让人感到困惑,而且它真的不会给你带来太多好处。
底线:不要将值与 false
或 true
进行比较。不要写:
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 anint
... §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 == _Bool
、int == short
、int == 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 thata == 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 thata == true
would evaluate to(bool)a == true
which actually would be true?
答案的顶部解决了这个问题:true
在 int
中,因此 (bool)a
在比较之前被提升为 int
作为 int
排名高于 _Bool
.