为什么 C 在 C99 之前没有布尔数据类型?
我知道你可以#define
一些整数,但为什么 C 在 C99 之前没有专用的布尔数据类型?
这在编程和逻辑中很常见,我不明白缺乏显式类型和符号。
I realise you can just #define
some integers, but why didn't C have a dedicated boolean data type before C99?
It's such a common occurence in programming and logic, I don't understand the absense of an explicit type and notation.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
如果你在图书馆呆了一点时间,你就不必猜测。
以下是摘自Dennis Ritchie 关于 C 语言演变的论文的一些陈述。背景是 Dennis 正在 Ken Thompson 的语言 B 上构建,该语言是在非常小的 PDP-7(一种字寻址机器)上实现的。由于兴趣日益浓厚,该小组获得了第一批 PDP-11 之一。丹尼斯写道,
(重点是我的。)
本文接着描述了 Dennis 为发明新的指针语义而做出的努力,以使得数组可以工作,并接受这个新奇的
struct
想法。类型安全的概念以及区分布尔值和整数的概念直到很久以后才显得重要:-)If you spend a little time in the library, you don't have to speculate.
Here are some statements taken from Dennis Ritchie's paper on the evolution of C. The context is that Dennis is building on Ken Thompson's language B, which was implemented on the very tiny PDP-7, a word-addressed machine. Because of growing interest, the group got one of the very first PDP-11s. Dennis writes,
(Emphasis mine.)
The paper goes on to describe Dennis's struggles to invent a new pointer semantics, to make arrays work, and to come to terms with this newfangled
struct
idea. Notions of type safety and distinguishing Booleans from integers did not seem important until much later :-)C 实际上只不过是一种高级汇编语言。是的,它有控制结构等等,甚至还有汇编器肯定不需要的类型。
但该语言是几十年前设计的。由于每个布尔结果都归结为处理器状态字中的各个位,因此显然仅使用整数数据类型就足够了。它使编译器可能不那么复杂,因为您可以省略一些类型检查(在后来的语言中,控制结构需要一个布尔值,在C中,它们只需要0或其他整数值) 。
C is actually little more than a higher-level assembly language. Yes, it got control structures and whatnot and it even got types which assembler certainly doesn't need.
But the language was designed decades ago. And since every boolean result gets down to individual bits in the processor's status word it obviously was sufficient to just using an integral data type for it. And it made the compiler probably a little less complex since you can omit some type checking (in later languages control structures need a boolean value, in C they just need an integral value of either 0 or something else).
CPU没有“布尔类型”,它们只处理字节和它们的倍数,因此布尔类型在当时没有任何意义,因为它没有带来优势(当你只能检查“is 0”时为什么要使用类型或“不为空”)
A CPU has no "boolean type", they only work on bytes and multiples of them so a boolean type made no sense at that time as it didn't give an advantage (why use a type when you can only check "is 0" or "is not null")
将零视为假并将任何非零视为真是很常见的(并且在某些情况下仍然如此)。这对速记有好处:例如,您可以只使用
while (remaining)
而不是while (remaining != 0)
。一些语言标准化为真 -1。原因是,在补码表示法(大多数计算机用它来表示负数)中,0 的按位非是 -1(在 8 位二进制中,
11111111
是十进制 -1 )。随着时间的推移,人们意识到使用编译器定义的常量可以防止许多潜在的混乱。自从我完成 C++ 以来已经有一段时间了,但我相当确定任何非零值仍然会评估为“true”。
It was common (and still is in some cases) to treat zero as false and any non-zero as true. This has advantages for shorthand: for example, instead of
while (remaining != 0)
you can just usewhile (remaining)
.Some languages standardised on true being -1. The reason for this is that in twos-complement notation (which most computers use to represent negative numbers), the bitwise-not of 0 is -1 (in 8-bit binary ,
11111111
is decimal -1).Over time it was realised that using a compiler-defined constant would prevent a lot of potential confusion. It's been a while since I've done C++, but I'm fairly sure any non-zero value will still evaluate "true".
我怀疑拥有一个整数类型就足够了,0 为假,任何非 0 为真。
I suspect it was deemed sufficient to have an integer type, with 0 being false and anything not 0 true.
旧 C 并不是真正“缺少”布尔类型 - 只是所有整型类型也被认为适合执行双重任务,即存储布尔值。我可以看到这样做的两个主要原因:
位寻址处理器根本不常见(现在仍然不常见),因此编译器实际上无法使用“真正的布尔”类型来保存任何空间 - 无论如何,布尔值仍然至少与
char
一样大(如果您希望有效地访问它)。无论如何,比
int
窄的类型都会在表达式中扩展为int
- 因此布尔运算符仍然适用于int
操作数。..所以看起来没有足够令人信服的案例来证明专用的布尔类型实际上可以带来实际的好处。
请记住,C 语言确实有一组产生布尔结果的运算符(定义为 0 或 1) -
!
、&&
、| |
、!=
、==
、<
、<=
、>
和>=
- 所以它只是一个不存在的专用布尔类型。Old C wasn't really "missing" a boolean type - it was just that all of the integral types were also considered suitable for doing doubly-duty, storing booleans. I can see two main reasons for this:
Bit-addressing processors weren't at all common (and still aren't), so the compiler wouldn't really be able to use a "true boolean" type to save any space - the boolean would still be at least as big as a
char
anyway (if you hoped to access it efficiently).Types narrower than
int
are widened toint
in expressions anyway - so the boolean operators would still work onint
operands...so it just looks like there wasn't a compelling enough case that a dedicated boolean type would actually convey practical benefits.
Remember that the C language does have a set of operators that produce boolean results (defined to be either 0 or 1) -
!
,&&
,||
,!=
,==
,<
,<=
,>
and>=
- so it's only a dedicated boolean type that's not there.用于存储布尔值的类型(通常)体现了空间和时间之间的权衡。通过使用 int (通常为四个字节),您通常会获得最快的结果(至少对于单个操作)。另一方面,如果您使用很多字节,那么使用一个字节甚至打包它们会更有意义,这样您存储的每个值仅使用一位——但是当/如果您这样做时,读取或写入单个位变得更加昂贵(并且使用额外的代码)。
由于没有一个答案是真正“正确”的,因此他们将决定留给用户根据他们正在编写的程序的要求做出。
那么,真正的问题是为什么在 C99 中添加布尔类型。我的猜测是涉及几个因素。首先,他们意识到程序员的可读性和便利性现在通常比提供绝对最佳性能更重要。其次,编译器现在可以进行更多的全局分析,因此至少可以猜测有人可能编写一个编译器来尝试选择最适合特定程序的表示形式(尽管我不这样做)不知道有什么真正的)。
The type you use to store a Boolean (usually) embodies a trade-off between space and time. You'll typically get the fastest results (at least for an individual operation) by using an int (typically four bytes). On the other hand, if you're using very many, it can make a lot more sense to use one byte or even pack them so each value you're storing uses only a single bit -- but when/if you do that, reading or writing a single bit becomes substantially more expensive (and uses extra code).
Since there was no one answer that was really "right", they left the decision to the user to make based on the requirements of the program they were writing.
The real question, then, is why a Boolean type was added in C99. My guess is that a couple of factors are involved. First, they realized that readability and convenience for the programmer is now usually more important than giving the absolute best performance possible. Second, compilers now do quite a bit more global analysis, so it's at least possible to guess that somebody might write a compiler that tries to pick a representation that's most appropriate for a particular program (though I don't know of any that really does).
历史原因,可能是:
受 ALGOL 影响很大的 CPL,很可能有布尔类型,但我的 google-fu 不足以找到这方面的参考。但 CPL 对于当时来说过于雄心勃勃,因此产生了一个名为 BCPL 的精简版本,它的好处是您可以在可用的硬件上实际实现它。
BCPL 只有一种类型 - “单词” - 如果
0
在布尔上下文中被解释为 false,如果~0
则被解释为 true(意味着的补集) 0
,如果解释为有符号补码整数,则表示值-1
。任何其他值的解释取决于实现。在仍然无类型的后继者 B 之后,C 重新引入了类型系统,但它仍然受到其前辈的无类型性质的严重影响。
Historical reasons, probably:
CPL, which was heavily influenced by ALGOL, most likely had a boolean type, but my google-fu didn't suffice to find a reference for this. But CPL was too ambitious for its time, resulting in a stripped-down version called BCPL, which had the benefit that you could actually implement it on available hardware.
BCPL only had a single type - the 'word' - which was interpreted as false in boolean contexts if
0
and as true if~0
(meaning the complement of0
, which would represent the value-1
if interpreted as signed twos-complement integer). The interpretation of any other value was implementation dependant.After the still typeless successor B, C reintroduced a type system, but it was still heavily influenced by the typeless nature of its predecessors.
添加与整数不兼容的单独“布尔”类型会使编译器比简单地使用整数更复杂。拥有与整数兼容的单独布尔类型使得有必要指定存储非 0 值的可能后果
或 1 到布尔对象中,或对布尔值执行数值计算
其表示形式既不包含与关联的位模式的对象
“0”也不是“1”。假设:
如果 intFunction 返回任何非零值,则要求 someInt 必须接收值 1 通常会使上述内容比
需要前语义的情况更昂贵,它们可以在不使用布尔类型的情况下实现,通过:
由于使用布尔类型可以完成的任何事情也可以在没有它们的情况下完成,并且在许多情况下使用字符类型的代码可以比布尔类型更有效,所以我建议从来没有(并且仍然没有)任何真正的需要他们。
Adding a separate "Boolean" type which isn't compatible with integers would have made the compiler more complicated than simply using integers for the purpose. Having a separate Boolean type which is compatible with integers makes it necessary to specify the possible consequences of storing a value other than 0
or 1 into a Boolean object, or performing numeric computations on a Boolean
object whose representation contains neither the bit pattern associated with
"0" nor "1". Given:
requiring that someInt must receive the value 1 if intFunction returns any non-zero value would generally make the above more expensive than
In cases where the former semantics would be required, they could be achieved without the use of a Boolean type, via:
Since anything that can be done using Boolean types can also be done without them, and in many cases code which uses character types can be more efficient than Boolean types, I'd suggest that there never was (and still isn't) any real need for them.
因为他们没有放一个进去。抱歉,如果这听起来很尖刻,但基本上它没有这样定义。
记住大多数人#define TRUE 和 FALSE。
你可能会说 bool 是标准 - 但显然它在 C99 之前不是标准 - 这是 10 年前制定的;)当它变得明显缺失时,他们添加了它。
Because they did not put one in. Sorry if that sounds snippish, but basically it was not defined as such.
Remember most people #define TRUE and FALSE.
You may say bool IS standard - but obviously it WAS not standard before C99 - which was made 10 years ago ;) They added it then when it became obvious a missing item.
因为没有人可以预见一切,包括编程语言中缺少的数据类型。
Because none can foresee everything including missing data type in a programming language.