代码之家  ›  专栏  ›  技术社区  ›  Reto Meier

为什么C在C99之前没有布尔数据类型?

  •  37
  • Reto Meier  · 技术社区  · 15 年前

    我知道你可以 #define 一些整数,但是为什么C在C99之前没有一个专用的布尔数据类型?

    这是编程和逻辑中常见的现象,我不理解显式类型和符号的缺失。

    11 回复  |  直到 7 年前
        1
  •  24
  •   bishop    7 年前

    如果你花一点时间在图书馆,你就不必猜测了。 这是一些陈述 Dennis Ritchie's paper on the evolution of C . 上下文是丹尼斯在KenThompson的语言B上构建的,该语言在非常小的pdp-7(一种字寻址机器)上实现。由于兴趣的增长,该组织得到了最早的一个PDP-11。

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

    b和bcpl模型暗示了处理指针时的开销:语言规则,通过将指针定义为单词数组中的索引,强制将指针表示为单词索引。每个指针引用都生成一个从指针到硬件期望的字节地址的运行时比例转换。

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

    (强调我的)

    本文接着描述了丹尼斯在发明一种新的指针语义、使数组工作以及适应这种新的语言方面的努力。 struct 想法。类型安全和区分布尔值和整数的概念直到很久以后才显得重要:—)

        2
  •  17
  •   Joey Gumbo    15 年前

    实际上,C只是一种更高级的汇编语言。是的,它有控制结构和其他什么,甚至还有汇编程序当然不需要的类型。

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

        3
  •  10
  •   Morfildur    15 年前

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

        4
  •  10
  •   Dan Puzey    15 年前

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

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

    随着时间的推移,人们认识到使用编译器定义的常量可以避免许多潜在的混淆。我做C++已经有一段时间了,但是我很确定任何非零值仍然会评估“true”。

        5
  •  7
  •   Vatine    15 年前

    我怀疑它被认为足够有一个整数类型,0是假的,任何不是0的东西都是真的。

        6
  •  5
  •   Jerry Coffin    15 年前

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

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

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

        7
  •  5
  •   caf    15 年前

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

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

    • 类型窄于 int 扩大到 利息 总之,在表达式中-因此布尔运算符仍然可以处理 int 操作数。

    …所以看起来没有一个足够令人信服的例子,一个专用的布尔类型实际上可以传达实际的好处。

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

        8
  •  4
  •   Christoph    15 年前

    历史原因,可能是:

    CPL受algol的影响很大,很可能是布尔型的,但我的google fu不足以找到这方面的参考。但CPL当时太雄心勃勃了,导致了一个名为BCPL的精简版本,它的好处是您可以在可用的硬件上实现它。

    bcpl只有一个类型——“word”——在布尔上下文中,如果 0 如果是真的 ~0 (意思是对 ,表示该值 -1 如果解释为有符号的两个补整数)。任何其他价值的解释取决于实施情况。

    在仍然没有排字的后继b之后,c重新引入了一种类型系统,但它仍然受到其前辈的无排字性质的严重影响。

        9
  •  2
  •   supercat    7 年前

    添加与整数不兼容的单独“布尔”类型会使编译器比简单地使用整数更复杂。具有与整数兼容的单独布尔类型,因此有必要指定存储0以外的值的可能结果。 或1到布尔对象中,或对布尔值执行数值计算 对象,其表示形式既不包含与 “0”也不是“1”。鉴于:

    someBool = intFunction();
    someInt = someBool;
    

    如果IntFunction返回任何非零值,则要求someInt必须接收值1,这通常会使上面的值比

    someChar = intFunction();
    someInt = someChar;
    

    在需要前一种语义的情况下,无需使用布尔类型即可实现,方法如下:

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

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

        10
  •  1
  •   TomTom    15 年前

    因为他们没有把一个放进去。很抱歉,如果这听起来很尖刻,但基本上它没有被定义为这样。

    记住,大多数人都会定义“真”和“假”。

    你可能会说bool是标准的——但很明显,它在c99之前不是标准的——c99是10年前制造的;)他们添加了它,然后当它变得明显是丢失的物品时。

        11
  •  0
  •   Eugeniu Torica    15 年前

    因为没有人能预见到任何事情,包括编程语言中丢失的数据类型。