为什么在 C99 中 false 和 true 被定义为 0 和 1,而不是 ((bool)0) 和 ((bool)1)?
我刚刚偶然发现了一个失败的断言,因为它将 false 与函数的返回类型进行了比较,因为函数本身返回了 bool,并且断言不仅检查了值,还检查了返回值的类型匹配 false ,保证返回一个 bool 值。
现在的问题是 C99 将 bool 定义为 _Bool 并且 _Bool 甚至不一定与int (事实上,根据我的经验,在当今的大多数平台上,它通常与 unsigned char 大小相同),更不用说是相同类型了(这实际上是不可能的,如 _Bool是 C99 中语言的内置类型),但将 false 和 true 定义为 0 和 1,没有任何类型转换和 没有类型转换的预处理器定义将默认为 int。
如果 C99 将 false 和 true 定义为 ((bool)0) 和 ((bool)1),则无论 _Bool 是如何定义的,它们将始终是 bool 类型。
那么,是否有充分的理由将它们始终定义为整数,即使 bool 在该平台上不是整数,或者这只是语言中的一个错误,应该使用 C1x?
I just stumbled across an assert that failed, as it compared false to the returntype of a function, as the function itself returned a bool and the assert checked not only the value, but also the type of the returnvalue to match the one of false, to guarantee, that a bool is returned.
Now the problem is that C99 defines bool as _Bool and _Bool is even not necessarily the same size as int (in fact, in my experience, on most platforms nowadays, it is often the same size as unsigned char), not to talk about being the same type (which is actually impossible, as _Bool is a builtin type of the language in C99), but defines false and true as 0 and 1 without any typecast and preprocessor definitions without a typecast will default to int.
If C99 would instead define false and true as ((bool)0) and ((bool)1), they would always be of type bool, no matter, how _Bool is defined.
So is there a good reason to have them always defined as ints, even when bool is not an int on that platform or is this just a bug in the language that should be fixed with C1x?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
false
和true
分别定义为整数常量0
和1
,因为这正是 C99 标准所指定的在7.16部分:编辑:正如下面的评论所示,我似乎稍微误解了这个问题,我应该提供标准这样指定的原因。我能想到的一个原因是
true
和false
应该可以在#if
预处理指令中使用(如标准中的引用)提到)。((bool) 0)
或((bool) 1)
在#if
预处理指令中不起作用的原因是因为标准不允许。在 6.10.1 节中,它说:false
andtrue
are defined as the integer constants0
and1
respectively, because that's exactly what the C99 standard specifies in section 7.16 :EDIT : as the comments below indicate, it seems I slightly misinterpreted the question, and I should have provided the reason the standard specifies it like that. One reason I can think of, is that
true
andfalse
are supposed to be usable in#if
preprocessing directives (as the quote from the standard mentions).The reason
((bool) 0)
or((bool) 1)
won't work in#if
preprocessing directives, is because the standard doesn't allow it. In section 6.10.1 it says :除了已经提到的其他原因之外,因为只要您对
_Bool
执行了几乎任何操作,它就会变成int
。例如,
(_Bool)0 & 的类型是什么? (_Bool)1
?您可能认为表达式的类型为_Bool
,但实际上 §6.5.10 定义了&
的语义:“通常的算术转换”在 C 标准中具有非常特定的含义。它在 §6.3.1.8 中定义,包括以下内容:
“整数提升”也是一个定义的术语,来自 §6.3.1.1:
尽管 C 标准中存在比
int
更窄的类型,但它们在几乎任何表达式中都会自动扩展为int
。再加上布尔运算的结果具有int
类型这一事实,这使得int
成为这些文字类型的自然选择。Beyond the other reasons already mentioned, because a
_Bool
becomes anint
anyway as soon as you do almost anything with it.For example, what is the type of
(_Bool)0 & (_Bool)1
? You might think that the expression has type_Bool
, but actually §6.5.10 defines the semantics of&
:"usual arithmetic conversions" has a very specific meaning in the C standard. It is defined in §6.3.1.8, and includes the following:
"integer promotions" is also a defined term, from §6.3.1.1:
Although narrower types than
int
exist in the C standard, they are automatically widened toint
in nearly any expression. Together with the fact that the result of the boolean operations has typeint
, this makesint
a natural choice for the type of these literals.所有其他答案都试图使用该标准来证明为什么该标准以某种方式定义事物,我觉得这并不令人满意。该标准不仅定义了类型,还定义了运算符和预处理器,因此,如果 C99 引入了布尔类型,为什么不更改所有布尔运算符以计算该类型的值并扩展预处理器以支持布尔类型呢?
这样做是可能的,但需要更复杂。对于标准编写者和编译器编写者来说,只需进行最少的必要更改即可向语言添加新的布尔类型,这要容易得多。由于所有布尔运算仍然计算为 int 类型,因此所有 C99 之前的编译器都可以更新为支持 C99,而无需更改所有基本运算符的类型计算代码,并且标准编写者可以更加确信新的布尔功能不会意外地给标准中以前正常的部分带来不一致。他们所需要做的就是确保“通常的算术转换”应用于
_Bool
,然后其他一切都可以保证正常工作。这不是技术原因。这是一个实用的。
All the other answers are trying to use the standard to justify why the standard defines things a certain way, which I find unsatisfactory. The standard defines not only the types, but also the operators and the preprocessor, so if C99 was introducing a Boolean type, why not change all the Boolean operators to evaluate to a value of that type and extend the preprocessor to support Boolean types?
To do so would be possible, but more complicated the necessary. It was far easier for the standard-writers and the compiler-writers to make only the minimum necessary changes to add a new Boolean type to the language. Since all the Boolean operations still evaluate to type
int
, all the pre-C99 compilers can be updated to support C99 without having to change their type-evaluation code for all the basic operators, and the standard-writers can be more confident that the new Boolean feature hasn't accidentally introduced inconsistencies to parts of the standard that had previously been fine. All they needed to do was make sure the "usual arithmetic conversions" applied to_Bool
, and then everything else is guaranteed to work.It's not a technical reason. It's a practical one.
首先,虽然
_Bool
可能不是int
,但要求_Bool
可以接受值 0 和 1,因此扩展true
和false
为 1 和 0 就可以了。此外,为了向后兼容,
true
和false
合理地为int
,因为所有逻辑运算符都返回int
。最后,如 @Sander De Dycker 提到,标准定义的
true
和false
可以这样扩展(C99 §7.16/3)。Firstly, although
_Bool
may not beint
, it is required that a_Bool
can accept the values 0 and 1, therefore expandingtrue
andfalse
to 1 and 0 are fine.Also, for backward compatibility,
true
andfalse
are reasonable to beint
s, because all logical operators returnint
.And finally, as @Sander De Dycker mentioned, the standard defined
true
andfalse
be expanded like that (C99 §7.16/3).