在C中使用布尔值

Using boolean values in C

C没有任何内置的布尔类型。在C中使用它们的最佳方法是什么?


从好到坏:

选项1(C99)

1
#include <stdbool.h>

选项2

1
typedef enum { false, true } bool;

选项3

1
2
typedef int bool;
enum { false, true };

选项4

1
2
3
typedef int bool;
#define true 1
#define false 0

解释

  • 只有当你使用C99并且它是"标准方法"时,选项1才有效。如果可能,选择此项。
  • 选项2、3和4在实践中具有相同的行为。#2和3虽然没有使用定义,但在我看来这更好。

如果你还没有决定,那就去1!


关于C语言布尔值的几点思考:

我已经足够大了,我只使用普通的int作为布尔类型,没有任何typedef,也没有为真/假值定义或枚举。如果按照下面我关于从不与布尔常量进行比较的建议,那么您只需要使用0/1来初始化标志。然而,这种做法在现代可能被认为过于反动。在这种情况下,必须使用,因为它至少有标准化的好处。

无论调用什么布尔常量,都只能将它们用于初始化。从来没有写过这样的东西

1
2
if (ready == TRUE) ...
while (empty == FALSE) ...

这些总是可以用更清晰的

1
2
if (ready) ...
while (!empty) ...

请注意,这些内容实际上可以合理地、可理解地大声读出。

给你的布尔变量取正数,即full,而不是notfull。后者导致代码难以读取。比较

1
2
if (full) ...
if (!full) ...

具有

1
2
if (!notfull) ...
if (notfull) ...

前两对都是自然读的,而!notfull即使是很难读,在更复杂的布尔表达式中也会变得更糟。

通常应避免使用布尔参数。考虑这样定义的函数

1
void foo(bool option) { ... }

在函数体中,参数的含义非常清楚,因为它有一个方便的、希望有意义的名称。但是,呼叫站点看起来像

1
2
foo(TRUE);
foo(FALSE):

在这里,如果不总是查看函数定义或声明,就根本不可能知道参数的含义,而且如果添加更多的布尔参数,情况会变得更糟。我也建议

1
2
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);

1
2
3
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }

无论哪种情况,呼叫站点现在看起来都像

1
2
foo(OPT_ON);
foo(OPT_OFF);

读者至少有机会在不深入了解foo的定义的情况下进行理解。


C中的布尔值是一个整数:0代表假,非0代表真。

请参阅布尔数据类型、C部分、C++、ObjuleC、AWK。


以下是我使用的版本:

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

因为false只有一个值,而逻辑true可以有多个值,但是技术将true设置为编译器将对false使用的值。

这就解决了一个问题,即有人编写了一些可以归结为以下内容的代码:

1
if (true == !false)

我想我们都会同意,这不是一个好的做法,而是一次性的成本做"真的"!错误"我们消除了这个问题。

[编辑]最后我使用了:

1
typedef enum { myfalse = 0, mytrue = !myfalse } mybool;

避免与其他定义truefalse的方案名称冲突。但是这个概念仍然是一样的。

[编辑]显示整数到布尔值的转换:

1
2
3
mybool somebool;
int someint = 5;
somebool = !!someint;

第一个(最右边)!将非零整数转换为0,然后转换为第二个(最左边)!将0转换为myfalse值。我将把它作为练习留给读者来转换一个零整数。


如果您使用的是C99编译器,它内置了对bool类型的支持:

1
2
3
4
5
6
#include <stdbool.h>
int main()
{
  bool b = false;
  b = true;
}

http://en.wikipedia.org/wiki/boolean_数据类型


第一件事。C,即ISO/IEC 9899已经有了19年的布尔类型。这比访问此问题时,业余/学术/专业部分结合在一起的C编程职业的预期时间要长得多。我的确实比这要快1-2年。这意味着,在一个普通的读者已经学会了关于C的任何东西的时候,C实际上已经有了布尔数据类型。

对于数据类型,#include ,使用truefalsebool。或者不包括,改为使用_Bool10

在这个答案中有很多危险的建议。我会告诉他们:

1
2
3
typedef int bool;
#define true 1
#define false 0

这不是否定的,因为一个不经意的读者——在那19年里学过C——会期望bool指的是实际的bool数据类型,并且行为类似,但事实并非如此!例如

1
2
double a = ...;
bool b = a;

C99-bool/_Bool时,如果a为零,则将b设为false,否则设为true。当typedef就位时,double将被强制为int——如果double的值不在int的范围内,则行为不确定。

当然,如果truefalse是在enum中声明的,也同样适用。

更危险的是申报

1
2
3
typedef enum bool {
    false, true
} bool;

因为现在除了1和0之外的所有值都是无效的,如果将这样的值赋给该类型的变量,那么行为将完全未定义。

因此,如果由于某些无法解释的原因,您不能使用C99,对于布尔变量,您应该使用:

  • 类型int和值01原样;小心地从任何其他值到这些值进行域转换,并使用双负!!进行域转换。
  • 或者,如果你坚持认为你不记得0是错误的和非零的,至少使用大写,这样他们就不会与c99概念混淆:booltruefalse


1
2
3
4
typedef enum {
    false = 0,
    true
} t_bool;


C有一个布尔类型:bool(至少对于最后10个!!)年)

包括stdbool.h和true/false将按预期工作。


在布尔运算中,任何非零的值都被计算为真,因此

1
2
#define TRUE 1
#define FALSE 0

并使用常量。


@托马斯·马修斯:如果条件表达式非零,则视为真,但C标准要求逻辑运算符本身返回0或1。

@汤姆:定义为真!错误是坏的,完全没有意义。如果头文件进入编译的C++代码,那么它会导致问题:

1
2
3
4
5
6
void foo(bool flag);

...

int flag = TRUE;
foo(flag);

一些编译器将生成有关int=>bool转换的警告。有时人们会通过这样做来避免:

1
foo(flag == TRUE);

强制表达式为C++布尔。但如果你定义为真!错误,最终结果是:

1
foo(flag == !0);

最后做了一个int-to-bool比较,无论如何都会触发警告。


如果允许使用C99,只需对其他答案和一些澄清进行补充。

1
2
3
4
5
6
7
8
9
10
11
+-------+----------------+-------------------------+--------------------+
|  Name | Characteristic | Dependence in stdbool.h |        Value       |
+-------+----------------+-------------------------+--------------------+
| _Bool |   Native type  |    Don't need header    |                    |
+-------+----------------+-------------------------+--------------------+
|  bool |      Macro     |           Yes           | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
|  true |      Macro     |           Yes           |   Translate to 1   |
+-------+----------------+-------------------------+--------------------+
| false |      Macro     |           Yes           |   Translate to 0   |
+-------+----------------+-------------------------+--------------------+

我的一些偏好:

  • _Bool还是bool?两者都很好,但是bool看起来比关键字_Bool好。
  • bool_Bool的可接受值为:falsetrue。指定01而不是falsetrue是有效的,但是很难阅读和理解逻辑流。

标准中的一些信息:

  • _Bool不是unsigned int,而是组无符号整数类型的一部分。它的大小足以容纳01的值。
  • 不要,但是的,你可以重新定义booltruefalse,但肯定不是一个好主意。这种能力被认为是过时的,将来会被移除。
  • 将标量类型(算术类型和指针类型)赋给_Boolbool,如果标量值等于0或与0比较,则为0,否则结果为1_Bool x = 9;9在赋给x时转换为1
  • _Bool是1字节(8位),通常程序员会尝试使用其他位,但不推荐使用,因为给出的唯一保证是只使用一个位来存储数据,而不像char类型的8位可用。


您可以使用一个字符或另一个小数字容器。

伪码

1
2
3
4
#define TRUE  1
#define FALSE 0

char bValue = TRUE;


就是这样:

1
2
#define TRUE 1
#define FALSE 0


您可以简单地使用如下定义指令:

1
2
3
4
#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;

使用方法如下:

1
2
3
bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);

所以……