44

我意识到你可以只使用#define一些整数,但为什么 C 在 C99 之前没有专用的布尔数据类型?

这在编程和逻辑中很常见,我不明白显式类型和符号的缺失。

4

11 回答 11

28

如果你在图书馆花一点时间,你就不必猜测了。以下是Dennis Ritchie 关于 C 演化的论文中的一些陈述。上下文是 Dennis 是在 Ken Thompson 的语言 B 上构建的,该语言是在非常小的 PDP-7 上实现的,这是一种字寻址机器。由于兴趣日益浓厚,该小组获得了首批 PDP-11 之一。丹尼斯写道,

PDP-11 的出现暴露了 B 语义模型的几个不足之处。首先,它从 BCPL 继承而来的字符处理机制很笨拙:使用库过程将打包的字符串分散到单个单元格中,然后重新打包,或者访问和替换单个字符,开始感到尴尬,甚至愚蠢,在面向字节的机器。

B 和 BCPL 模型隐含了处理指针的开销:语言规则通过将指针定义为单词数组中的索引,强制将指针表示为单词索引。每个指针引用生成从指针到硬件预期的字节地址的运行时标度转换。

由于所有这些原因,似乎需要一种打字方案来处理字符和字节寻址,并为即将到来的浮点硬件做准备。其他问题,特别是类型安全和接口检查,在当时似乎并不像后来那样重要。

(强调我的。)

这篇论文继续描述了丹尼斯为发明一种新的指针语义、使数组工作以及接受这个新奇struct想法而付出的努力。直到很久以后,类型安全和区分布尔值和整数的概念才显得重要:-)

于 2010-03-11T21:01:10.717 回答
17

C 实际上只是一种高级汇编语言。是的,它有控制结构和诸如此类的东西,它甚至有汇编程序当然不需要的类型。

但是这种语言是几十年前设计的。而且由于每个布尔结果都归结为处理器状态字中的各个位,因此显然只使用整数数据类型就足够了。它使编译器可能不那么复杂,因为您可以省略一些类型检查(在后来的语言中,控制结构需要一个布尔值,在 C 中它们只需要一个整数值 0 或其他值)。

于 2010-03-11T15:09:32.377 回答
11

CPU 没有“布尔类型”,它们只适用于字节和它们的倍数,因此布尔类型在当时没有任何意义,因为它没有优势(为什么在只能检查“为 0”时使用类型或“不为空”)

于 2010-03-11T15:12:11.187 回答
11

将零视为假而将任何非零视为真是常见的(在某些情况下仍然如此)。这对速记有好处:例如,while (remaining != 0)您可以使用while (remaining).

一些语言标准化为真实存在-1。原因是在二进制补码表示法(大多数计算机用来表示负数)中,0 的按位非是 -1(在 8 位二进制中,11111111是十进制的 -1)。

随着时间的推移,人们意识到使用编译器定义的常量可以防止很多潜在的混淆。自从我完成 C++ 以来已经有一段时间了,但我相当确定任何非零值仍然会评估“真”。

于 2010-03-11T15:14:48.187 回答
8

我怀疑拥有一个整数类型就足够了,0 为假,任何不为 0 的都是真。

于 2010-03-11T15:10:56.733 回答
7

旧 C 并没有真正“缺少”布尔类型——只是所有的整数类型也被认为适合做双重任务,存储布尔值。我可以看到两个主要原因:

  • 位寻址处理器根本不常见(现在仍然不常见),因此编译器将无法真正使用“真正的布尔”类型来节省任何空间 - 布尔值仍然至少与char无论如何(如果您希望有效地访问它)。

  • 无论如何,类型比表达式int中的范围更窄int- 所以布尔运算符仍然可以处理int操作数。

..所以看起来没有足够令人信服的案例来证明专用的布尔类型实际上会带来实际的好处。

请记住,C 语言确实有一组产生布尔结果的运算符(定义为 0 或 1) - !, &&, ||, !=, ==, <, <=,>>=- 所以它只是一个不存在的专用布尔类型。

于 2010-03-12T00:03:25.987 回答
7

您用来存储布尔值的类型(通常)体现了空间和时间之间的权衡。通过使用 int(通常为四个字节),您通常会获得最快的结果(至少对于单个操作)。另一方面,如果你使用很多,使用一个字节甚至打包它们会更有意义,这样你存储的每个值只使用一个位——但是当/如果你这样做,读取或写入单个位变得更加昂贵(并使用额外的代码)。

由于没有一个答案是真正“正确”的,因此他们将决定留给用户根据他们正在编写的程序的要求做出。

那么,真正的问题是为什么在 C99 中添加了布尔类型。我的猜测是涉及几个因素。首先,他们意识到程序员的可读性和便利性现在通常比提供绝对最佳性能更重要。其次,编译器现在做了更多的全局分析,所以至少可以猜测有人可能会编写一个编译器来尝试选择最适合特定程序的表示(尽管我不知道有什么真正做到的) )。

于 2010-03-11T15:25:26.593 回答
5

历史原因,大概:

受 ALGOL 严重影响的 CPL 很可能具有布尔类型,但我的 google-fu 不足以为此找到参考。但 CPL 在当时过于雄心勃勃,因此产生了一个名为 BCPL 的精简版本,它的好处是您可以在可用的硬件上实际实现它。

BCPL 只有一种类型——“word”——在布尔上下文中被解释为 false if0和 true if ~0(意思是 的补码,如果解释为有符号二进制补码整数0,则表示该值)。-1任何其他值的解释取决于实现。

在仍然无类型的继任者 B 之后,C 重新引入了类型系统,但它仍然深受其前辈的无类型性质的影响。

于 2010-03-11T15:55:31.707 回答
2

添加一个与整数不兼容的单独“布尔”类型会使编译器比简单地使用整数更复杂。拥有与整数兼容的单独布尔类型使得有必要指定将 0 或 1 以外的值存储到布尔对象中的可能结果,或者对表示不包含与“相关的位模式”的布尔对象执行数值计算的可能结果0”或“1”。鉴于:

someBool = intFunction();
someInt = someBool;

如果 intFunction 返回任何非零值,则要求 someInt 必须接收值 1 通常会使上述内容比

someChar = intFunction();
someInt = someChar;

在需要前一种语义的情况下,它们可以在不使用布尔类型的情况下通过以下方式实现:

someChar = !!intFunction();
someInt = someChar;

由于任何可以使用布尔类型完成的事情也可以在没有它们的情况下完成,并且在许多情况下,使用字符类型的代码比布尔类型更有效,我建议从来没有(现在仍然没有)任何真正的需要他们。

于 2017-10-23T23:23:13.647 回答
1

因为他们没有放一个。对不起,如果这听起来很短,但基本上它没有被定义为这样。

记住大多数人#define TRUE 和 FALSE。

你可能会说 bool 是标准的——但显然它在 C99 之前不是标准的——这是 10 年前制造的;)当它变得明显缺少项目时,他们添加了它。

于 2010-03-11T15:05:48.970 回答
0

因为没有人可以预见一切,包括编程语言中缺少的数据类型。

于 2010-03-11T15:08:48.640 回答