在C中使用布尔值

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

1559092 次浏览

在布尔运算中,任何非零的东西都被评估为true,所以你可以

#define TRUE 1#define FALSE 0

并使用常量。

C中的布尔值是一个整数:假为零,真为非零。

另见布尔数据类型,部分C,C++, Objective-C, AWK

从最好到最坏:

选项1(C99及更新版本)

#include <stdbool.h>

备选案文2

typedef enum { false, true } bool;

备选案文3

typedef int bool;enum { false, true };

备选办法4

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

补充说明

  • 选项1仅在您使用C99(或更新版本)并且它是执行此操作的“标准方法”时才有效。如果可能,请选择此选项。
  • 选项2、3和4实际上将具有相同的行为。#2和#3不使用#定义,在我看来这更好。

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

您可以为它使用char或其他小数容器。

伪代码

#define TRUE  1#define FALSE 0
char bValue = TRUE;

它是这样的:

#define TRUE 1#define FALSE 0
typedef enum {false = 0,true} t_bool;

C具有布尔类型:bool(至少在过去10(!)年)

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

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

#include <stdbool.h>int main(){bool b = false;b = true;}

http://en.wikipedia.org/wiki/Boolean_data_type

如果条件表达式非零,则认为它们为真,但C标准要求逻辑运算符本身返回0或1。

@Tom:#定义TRUE! FALSE很糟糕,而且毫无意义。如果头文件进入编译C++代码,那么它可能会导致问题:

void foo(bool flag);
...
int flag = TRUE;foo(flag);

一些编译器会生成有关int=>bool转换的警告。有时人们通过以下方式避免这种情况:

foo(flag == TRUE);

强制表达式为C++布尔值。但是如果你#定义TRUE! FALSE,你最终会得到:

foo(flag == !0);

这最终会进行一个int到bool的比较,无论如何都可以触发警告。

关于C中布尔值的一些想法:

我已经足够大了,我只使用普通的int作为我的布尔类型,没有任何typedef或特殊定义或枚举的真/假值。如果你遵循我下面的建议,永远不要与布尔常量进行比较,那么你只需要使用0/1来初始化标志。然而,这种方法在现代可能被认为过于反动。在这种情况下,绝对应该使用<stdbool.h>,因为它至少有标准化的好处。

无论调用什么布尔常量,仅将它们用于初始化。永远不要写这样的东西

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

这些总是可以被更清晰的取代

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

请注意,这些实际上可以合理且可以理解地大声朗读。

给您的布尔变量正名,即full而不是notfull。后者导致代码难以轻松阅读。比较

if (full) ...if (!full) ...

if (!notfull) ...if (notfull) ...

前两个对都是自然读取的,而!notfull即使是这样读取也很尴尬,并且在更复杂的布尔表达式中变得更糟。

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

void foo(bool option) { ... }

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

foo(TRUE);foo(FALSE):

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

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

#define OPT_ON true#define OPT_OFF falsevoid foo(bool option) { ... }

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

foo(OPT_ON);foo(OPT_OFF);

读者至少有机会在不挖掘foo定义的情况下理解它。

这是我使用的版本:

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

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

这解决了有人编码一些东西的问题,这些东西可以归结为:

if (true == !false)

我想我们都会同意这不是一个好的做法,但是为了“true=! false”的一次性成本,我们消除了这个问题。

[编辑]最后我用了:

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

以避免与定义truefalse的其他方案的名称冲突。但概念保持不变。

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

mybool somebool;int someint = 5;somebool = !!someint;

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

[编辑]我的风格是在需要特定值时使用枚举中值的显式设置,即使默认值相同。示例:因为false需要为零,所以我使用false = 0,而不是false,

[编辑]显示如何在使用gcc编译时限制枚举的大小:

typedef __attribute__((__packed__)) enum { myfalse = 0, mytrue = !myfalse } mybool;

也就是说,如果有人这样做:

struct mystruct {mybool somebool1;mybool somebool2;mybool somebool3;mybool somebool4;}

结构的大小将是4字节而不是16字节。

您可以简单地使用#define指令,如下所示:

#define TRUE 1#define FALSE 0#define NOT(arg) (arg == TRUE)? FALSE : TRUEtypedef int bool;

并使用如下:

bool isVisible = FALSE;bool isWorking = TRUE;isVisible = NOT(isVisible);

等等

先说第一件事。C,即ISO/IEC 9899有一个19年了的布尔类型。这比访问这个问题时业余/学术/专业部分的C编程生涯的预计长度要长得多。我的确实超过了也许只有1-2年。这意味着在普通读者对C有任何了解,C实际上有布尔数据类型期间。

对于数据类型,#include <stdbool.h>,并使用truefalsebool。或者不包含它,而是使用_Bool10


在本主题的其他答案中推广了各种危险实践。我将解决它们:

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

这是不可能的,因为一个普通的读者——在这19年里确实学习了C——会期望bool引用实际bool数据类型,并且会有类似的行为,但事实并非如此!例如

double a = ...;bool b = a;

对于C99bool/_Boolb将设置为falseiffa为零,否则true为零。

  1. 当任何标量值转换为_Bool时,如果值比较等于0,则结果为0;否则,结果为1。59)

脚注

59)NaN不比较等于0,因此转换为1。

有了typedefdouble将被强制转换为int-如果双精度的值不在int行为未定义的范围内。

当然,这同样适用于truefalseenum中声明的情况。

甚至更危险声明的是什么

typedef enum bool {false, true} bool;

因为现在除了1和0之外的所有值是无效的,并且应该将这样的值分配给该类型的变量行为将是完全不确定的

因此iff由于某种莫名其妙的原因,您不能使用C99,对于布尔变量,您应该使用:

  • 键入int和值01现状;并使用双重否定!!仔细地从任何其他值到这些值的域转换
  • 或者,如果你不记得0是假的和非零的,至少使用大写,这样它们就不会与C99概念混淆:BOOLTRUEFALSE

只是对其他答案的补充和一些澄清,如果你被允许使用C99。

+-------+----------------+-------------------------+--------------------+|  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,但肯定不是一个好主意。这个能力被认为是过时的,将来会被删除。
  • bool0(算术类型和指针类型)分配给_Boolbool,如果bool1值等于0或与0比较,则为0,否则结果为1_Bool x = 9;9在分配给x时转换为1
  • _Bool是1字节(8位),通常程序员会尝试使用其他位,但不推荐,因为唯一保证的是只有一位用于存储数据,而不是像类型char那样有8位可用。

您可以使用_Bool,但返回值必须是整数(1表示true,0表示false)。但是,建议像C++中那样包含和使用bool,如这个答复来自daniweb论坛,以及这个答案来自另一个stackoverflow问题:

_Bool:C99的布尔类型。仅当您维护已经为bool、true或false定义了宏的遗留代码时,才建议直接使用_Bool。否则,这些宏将在标头中标准化。包含该标头,您可以像在C++中一样使用bool。

如果您使用的是C99,那么您可以使用_Bool类型。不需要#include。不过,您确实需要将其视为整数,其中1true0false

然后您可以定义TRUEFALSE

_Bool this_is_a_Boolean_var = 1;

//or using it with true and false#define TRUE 1#define FALSE 0_Bool var = TRUE;

现在C99支持布尔类型,但你需要#include <stdbool.h>

示例:

#include <stdbool.h>
int main(){bool arr[2] = {true, false};
printf("%d\n", arr[0] && arr[1]);printf("%d\n", arr[0] || arr[1]);
return 0;}

输出:

01

这就是我使用的:

enum {false, true};typedef _Bool bool;

_Bool是C中的内置类型,用于布尔值。