bool in C23
Source: Dev.to
Introduction
Originally, C had no boolean type. Instead, int was used such that 0 was treated as false and any non‑zero value as true. While this worked, using int as a boolean has several problems.
Problems with int
One problem with using int as a boolean is clarity. Consider the function:
int strbuf_reserve(strbuf_f *sbuf, size_t res_len);
What does that function return? A simple boolean value? The number of bytes actually reserved? An error code? You have to read the documentation (if any) or the source code to know what the int means.
Consequently, many programmers defined their own boolean “type” in C, for example:
#define bool int /* or: typedef int bool; */
#define false 0
#define true 1
or using all‑caps versions. However, this can cause incompatibilities when different libraries define their own boolean type slightly differently, leading to warnings or errors.
Another issue is memory usage. In structures, an int occupies at least four bytes (on a 32‑bit system), whereas a true boolean value needs only a single bit, but practically it must be at least sizeof(char) (which is always 1).
_Bool in C99
The C Committee eventually added a boolean type to C in C99: _Bool. The leading underscore was chosen to avoid breaking existing programs that might already use bool as an identifier.
The standard also introduced macros:
#define bool _Bool
#define false 0
#define true 1
Including this header lets you use the conventional names bool, false, and true without breaking older code.
Interaction with _Generic (C11)
When C11 introduced _Generic, _Bool did not integrate smoothly:
#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
}
The call F(false) invokes f_int because false is a macro for 0, which has type 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
Unlike int, any non‑zero value cast to _Bool is implicitly converted to 1 (true), making its semantics more intuitive and well defined.
bool in C23
In C23 the Committee finally added a complete boolean type: bool. The keywords false and true are now part of the language, eliminating the _Generic issue observed with _Bool.
Ideally, bool could have been introduced in C11 alongside _Generic, but the addition in C23 finally provides a proper, native boolean type.
Conclusion
After more than a quarter of a century for _Bool and over half a century for bool, C now has a proper boolean type that is clearer, smaller than int, and always well defined.