C23 中的 bool

发布: (2025年12月19日 GMT+8 10:33)
4 min read
原文: Dev.to

Source: Dev.to

Introduction

最初,C 语言没有布尔类型。取而代之的是使用 int,其中 0 被视为 false,任何非零值被视为 true。虽然这样可以工作,但使用 int 作为布尔值会带来若干问题。

Problems with int

使用 int 作为布尔值的一个问题是可读性。考虑下面的函数:

int strbuf_reserve(strbuf_f *sbuf, size_t res_len);

这个函数返回什么?一个简单的布尔值?实际预留的字节数?错误码?你必须阅读文档(如果有的话)或源码才能知道 int 的含义。

因此,许多程序员在 C 中自行定义布尔“类型”,例如:

#define bool   int   /* or: typedef int bool; */
#define false  0
#define true   1

或者使用全大写的版本。然而,当不同库对布尔类型的定义略有差异时,就会导致不兼容,产生警告或错误。

另一个问题是内存使用。在结构体中,int 至少占用四个字节(在 32 位系统上),而真正的布尔值只需要一个位,实际使用时也至少需要 sizeof(char)(始终为 1)。

_Bool in C99

C 委员会最终在 C99 中为 C 添加了布尔类型:_Bool。选择前导下划线是为了避免破坏已经把 bool 当作标识符使用的旧程序。

标准还引入了宏:

#define bool  _Bool
#define false 0
#define true  1

包含此头文件后,你就可以使用传统的 boolfalsetrue 名称,而不会破坏旧代码。

Interaction with _Generic (C11)

C11 引入 _Generic 时,_Bool 的集成并不顺畅:

#include <stdio.h>

void f_bool(void) { }
void f_int(void)  { }

#define F(X)                              \
    _Generic((X),                        \
        bool: f_bool,                     \
        int : f_int                       \
    )( (X) )

int main(void) {
    bool b = false;
    F(b);          // calls f_bool
    F(false);      // calls f_int
}

调用 F(false) 会调用 f_int,因为 false 是一个宏,展开为 0,其类型为 int

Casting behavior

int   i1 = (int)0.5;        // = 0 (truncation)
_Bool b1 = (_Bool)0.5;      // = 1 (non‑zero → true)

int   i2 = (int)LONG_MAX;   // implementation‑defined
_Bool b2 = (_Bool)LONG_MAX; // = 1

int 不同,任何非零值强制转换为 _Bool 时都会隐式转换为 1(true),其语义更直观且定义明确。

bool in C23

C23 中,委员会终于加入了完整的布尔类型:bool。关键字 falsetrue 现在已成为语言的一部分,消除了 _Generic_Bool 之间出现的问题。

理想情况下,bool 本可以在 C11 与 _Generic 同时引入,但在 C23 的加入终于提供了一个合适的、原生的布尔类型。

Conclusion

经过 _Bool 超过四分之一个世纪以及 bool 超过半个世纪的演进,C 现在拥有了一个更清晰、比 int 更小且始终定义明确的布尔类型。

Back to Blog

相关文章

阅读更多 »