为什么C ++允许将算术或枚举值隐式转换为布尔值?

时间:2009-06-19 05:44:23

标签: c++ boolean

C ++标准在第4.12节中说明,

算术,枚举,指针或指向成员类型的指针的右值可以转换为bool类型的右值。将零值,空指针值或空成员指针值转换为false,将任何其他值转换为true。

这意味着以下代码有效,

if(5)
  std::cout << "WOW!";

它在语法上是有效的,但在语义上它没有任何意义。我的问题是为什么C ++允许这样奇怪的事情? AFAIK,它没有任何优势而不是混淆。

9 个答案:

答案 0 :(得分:21)

认为这是历史性的,也是C用来评估bool概念的副产品......

C没有使用布尔类型,并且在C的“向下到金属”范例中,设置为NULL的指针和数字类型等也隐式false

如果您将其视为“无/零== false”和“其他任何内容== true”,那么它确实有意义。

答案 1 :(得分:7)

实际上,在许多语言中,包括C / Python / Perl / BASIC非零整数/指针值 总是被认为是真的,0被认为是假的。

这是许多编程语言中的已知约定,所以没有理由,为什么这不适用于C ++?

问题是为什么在Java中不是这样?

答案 2 :(得分:3)

它来自C的产品。

另请注意,这些(逻辑上,如果不是计算上)等效:

if(x&amp;&amp; y || z)

if(x * y + z)

(我知道这是因为TI99 / 4a BASIC没有AND或OR操作,因此*和+必须执行双重任务,而在TI99 / 4a BASIC中,布尔值与C一样工作。

答案 3 :(得分:2)

我认为原因是历史。值得注意的是,下一个C ++版本(C ++ 0x,C ++ 1x)引入了不允许隐式转换为整数的范围枚举,使得以下代码格式错误

enum class X { A, B, C };
if(X::B) { ... }

但是,允许隐式转换为bool的数字对我来说是有意义的,但对于枚举而言,这对我来说没有多大意义,因为主要目的是枚举值列表 - 仅次要实际值我相信,大多数时候,普查员都很感兴趣。 Scoped枚举将需要演员

if(static_cast<bool>(X::B)) { ... }

这增加了一些类型安全性,即枚举所需的C兼容性到目前为止还不允许(我想如果禁止普通枚举,这会破坏很多代码)。

答案 4 :(得分:1)

这是特定硬件限制的工件。

术语“int”,“short”,“bool”等。人。只要编译器工作,它只有真正不同的语义含义 - 在运行时,它只是1个字(8位)值,2个字(16位)值,4个字(32位)值等。

所以真正的问题不是“为什么C ++除了5作为布尔值”,而是“为什么C?”答案是,由于内存对齐,在所有情况下都不可能在任何地方存储单个位,因此编译器只使用了整个单词。在C ++中有一个指定的“bool”类型的事实只是一些词汇挥手。

答案 5 :(得分:0)

这是猜想,但我认为这是因为C被设计为极简主义语言。

首先,布尔评估和算术评估非常相似,它们实际上是在C解析器中组合在一起的,这减少了解析器的整体大小--C ++继承了它。

其次,在汇编中测试非零结果通常使用单个操作码来执行,该操作码测试寄存器的零值,如果为真,则跳转到语句的“else”部分。如果该值不为零,则执行自然会流入语句的“if-true”部分。

答案 6 :(得分:0)

从历史上看,C是一个相对Weakly Typed language,旨在简化和提高效率而非稳健性。 Pascal和类似语言的类型更强 - 枚举,指针,整数和bool不能在表达式中随机混合和匹配。

C(和许多C ++)程序员在这种背景下长大,你经常会看到这样的惯用代码:

while (1)
   dosomething(); // repeats forever

..或......

char * pointer;

if (pointer)  // tests pointer for being != 0, which equals NULL.
  fred = *pointer;

就个人而言,尽管使用C / C ++超过20年,我仍然发现这第二个成语丑陋,因为它在一行中产生两个“隐藏”的演员/假设 - (NULL == 0),那个(0 == FALSE)。

答案 7 :(得分:0)

我找不到确切的引文,但总是说C将汇编语言的所有功能和灵活性与汇编语言的安全性和易用性相结合。

通常处理器没有布尔,整数,ptr类型。它们只是内存或寄存器中的数字。

我个人总是喜欢这个成语:

some_obj * thingy;
if (thingy) ...

这似乎是表达“东西存在”或“初始化”的自然而简洁的方式。但后来,我花了很多时间用汇编语言。

虽然我倾向于在Objective-C,Java,C#中使用“thingy == null”(或nil),因为你只是觉得不太确定这些语言会发生什么,远离硬件。在某些语言中,有人甚至可以覆盖“==”运算符。

您可以将“if(ptr)...”视为调用隐式“cast to boolean”运算符...

答案 8 :(得分:0)

那里有很好的答案,但我想指出一件事:即使你不能说boolean = numberboolean = pointer,仍然有意义if(number)或{{ 1}}构造。