bool是C语言的原生类型吗?

305

我注意到 Linux 内核代码使用了 bool,但是我认为 bool 是 C++ 类型。bool 是标准的 C 扩展吗(例如 ISO C90),还是 GCC 的扩展?


3
comp.lang.c FAQ 的第9节讨论了这个问题。 - Keith Thompson
2
直接链接:http://www.c-faq.com/bool/index.html - Ellen Spertus
1
Linux内核使用-std=gnu89,它作为C90的扩展支持_Bool。"include/linux/types.h"中有typedef _Bool bool; - Ian Abbott
1
另外,值得一提的是,Linux内核2.6.19是第一个使用typedef _Bool bool;(提交记录6e21828743247270d09a86756a0c11702500dbfb)并且需要GNU C 3.2或更高版本的内核。 - Ian Abbott
12个回答

421

bool 在当前的C语言标准(C99)中存在,但在C89/90中不存在。

C99中本地类型实际上被称为_Bool,而bool是由stdbool.h定义的标准库宏(预期解析为_Bool)。类型为_Bool的对象保持0或1,而truefalse也是stdbool.h中的宏。

顺便提一下,这意味着C预处理器将把#if true解释为#if 0,除非包含stdbool.h。与此同时,C++预处理器要求本身识别true作为一种语言字面量。


73
2011年发布了新的ISO C标准(在回答此问题后)。按惯例,ANSI已将ISO C11标准作为ANSI标准采纳。由于历史原因,“ANSI C”一词通常(但不正确地)指的是由ANSI C89 / ISO C90标准定义的语言。由于C标准现在首先由ISO发布,并且已经有三个ISO C标准,其采用水平各不相同,最好引用标准发布的年份(ISO C90、ISO C99、ISO C11),以避免任何混淆。 - Keith Thompson
13
这是否意味着 _Bool 占用了1位内存? - Geremia
35
@Geremia:不行。为什么?在 C 语言中,每个可寻址的对象都必须占用至少 1 字节。而且在现实生活中的实现中,_Bool 类型通常占用 1 字节的内存。然而,语言规范明确允许将 _Bool 用作位域类型,这意味着通过使用位域,可以将 _Bool 值压缩到一个单独的比特位中(在更大的结构体内部)。 - AnT stands with Russia
1
@AnT _Bool 值如何既可以直接寻址(即大小为 1 字节),又可以参与位域?一个 _Bool 数组仍然需要所有元素都是可寻址的(例如 _Bool* ptr = &boolArray[123])。 - Dai
1
运算符<返回一个整数——假为零,真为非零(我认为应该返回1,但我不想查了)。如果表达式的值是非零的(或者如果表达式是指针类型,则为非NULL),则if中的表达式将被计算并执行受控语句。 - Martin Bonner supports Monica
显示剩余3条评论

133

C99引入了一个内置的_Bool数据类型(详见维基百科),如果您#include <stdbool.h>,它会将_Bool提供为宏bool

您特别询问了Linux内核。它假定存在_Bool并自己提供了bool typedef在include/linux/types.h中。


28
为什么要这样做?是为了允许它未定义或重新定义,以避免在其定义可能与旧代码冲突的情况下发生冲突。 - Clifford

36

C99中使用 stdbool.h,但在C90中必须定义为typedef或enum:

typedef int bool;
#define TRUE  1
#define FALSE 0

bool f = FALSE;
if (f) { ... }

或者:

typedef enum { FALSE, TRUE } boolean;

boolean b = FALSE;
if (b) { ... }

5
请注意,这个typedef的行为与C99的bool和许多编译器的bit类型不同。例如,bool x=4294967296LL;bool x=0.1;在C99中会将x设置为1,但大多数typedef版本可能会将其设置为0。 - supercat

31

不,ISO C90 中没有 bool.

这是标准 C 中的关键字列表(非 C99):

  • auto
  • break
  • case
  • char
  • const
  • continue
  • default
  • do
  • double
  • else
  • enum
  • extern
  • float
  • for
  • goto
  • if
  • int
  • long
  • register
  • return
  • short
  • signed
  • static
  • struct
  • switch
  • typedef
  • union
  • unsigned
  • void
  • volatile
  • while

这是一篇讨论内核和标准中一些其他差异的文章:http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/index.html


6
就实际目的而言,只要没有良好的编译器支持,这真的很重要吗?即使是gcc直到最近也没有C99的一半功能,而MSVC没有大部分功能,可能永远都不会有... - Pavel Minaev
5
问者明确询问ISO C90。通常人们提到 ANSI C 时指的是 C90。我不使用,也没有计划使用 C99,我认为许多人持相同看法。 - BobbyShaftoe
6
楼上的BobbyShaftoe在评论中明确表示C90只是一个例子。 - Keith Thompson

27
/* Many years ago, when the earth was still cooling, we used this: */

typedef enum
{
    false = ( 1 == 0 ),
    true = ( ! false )
} bool;

/* It has always worked for me. */

18
初始值完全没有必要。 typedef enum { false, true }; 同样好用。如果您坚持更加明确,可以写成 typedef enum { false = 0, true = 1 };。(或者,如果您的编译器支持的话,只需包含 #include <stdbool.h>;这已经是标准14年了。) - Keith Thompson
14
初始值可能是不必要的,但是这个答案以非常优雅的方式选择它们,不使用任意的值,而是利用语言本身的语义,并让编译器进行决策。 - MestreLion
16
@MestreLion:这种语言本身的语义保证了 typedef enum { false, true } bool; 的预期工作方式。1 == 0! false 并不优雅,它们只是含糊其辞而已。编译器没有决策可做;它必须遵守语言定义的语义。 - Keith Thompson
17
@KeithThompson说:“我不认为它们是混淆的,我猜测作者的意图是选择最“自然”的值:false被设置为语言规定不等式应该评估为什么值,而true则被设置为其“相反”值(同样是任何那个值)。这样,人们就不必关心是{1,0},{-1,0},{0,1}等等,因为它保证在比较中起作用,因为它是使用比较进行制作的。” - MestreLion
4
任何了解 C 语言的人都知道 falsetrue 的数值。不了解 C 语言的人不是 C 代码的预期读者。而且,正如我所说,C 语言自上个千年以来就已经有了内置的布尔类型。 - Keith Thompson
5
@KeithThompson:你两个陈述都是正确的。#include <stdbool.h> 是过去十年中最好的解决方案 :) 我只是喜欢这个相当"语言无关"的技巧来选择值。 - MestreLion

12

_Bool 是 C99 中的一个关键字:它指定了一种类型,就像 intdouble 一样。

6.5.2

2 声明为 _Bool 类型的对象足够大,可以存储值 0 和 1。


9
C99在中通过使用定义了bool、true和false。

5

stdbool.h定义了宏truefalse,但请记住它们被定义为1和0。

这就是为什么sizeof(true)等于sizeof(int),对于32位架构���说,这个值是4。


2
自C23起,booltruefalse成为了C语言的关键字,不需要任何#includebool成为了基本内置数据类型之一。 _Bool仍然有效,并被视为“替代拼写”。
头文件<stdbool.h>仅提供过时的宏__bool_true_false_are_defined,该宏扩展为整数常量1
您可以在此处找到最新的草案: https://open-std.org/JTC1/SC22/WG14/www/docs/n2912.pdf

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接