在 C 中使用 true 和 false

Posted

技术标签:

【中文标题】在 C 中使用 true 和 false【英文标题】:Using true and false in C 【发布时间】:2011-01-16 06:43:10 【问题描述】:

据我所知,在 c 中使用布尔值有 3 种方法

    使用bool类型,从此使用true和false 使用预处理器定义#define FALSE 0 ... #define TRUE !(FALSE) 只是直接使用常量,即 1 和 0

还有其他我错过的方法吗?不同方法的优缺点是什么?

我想最快的是数字 3,2 仍然更容易阅读(尽管按位取反会稍微增加开销),1 是最易读的,不兼容所有编译器。

【问题讨论】:

你真的认为编译器会等到运行时来否定一个常量? 跟进,所以我看起来不像个混蛋,没有编译器实际上会浪费时间这样做。编译器是重型优化器,如果它知道结果总是相同的,它就会把它放在那里。它永远不会等到运行时评估int i = 12 + 3 * 4;;它只会说int i = 24;。担心这样的性能是一个常见问题,不要感到难过。优化最后出现,当它出现时,您必须对代码进行计时并查看汇编输出,而不是猜测。即使它确实花费了一个周期,我也会选择最易读的解决方案。只有当它被证明是一个 问题我是否会切换到更快的解决方案,对它们进行计时以确保它们确实更快。在可读性和循环之间进行选择时,请选择可读性。 :) 快速编写好代码很容易,但要编写好“快速”代码却很难。 使用宏时,请记住(x == TRUE)(x) 不同。只有当x 拥有TRUE 的值时,前者才成立。后者适用于任何非零值。 我建议不要定义特殊的布尔宏;这只会诱使新手程序员编写诸如if(foo == TRUE)if(foo == FALSE) 之类的东西,这在大多数语言中是一种暴行,但在C 中更是如此,其中任何标量值!= 0 在布尔上下文中都被认为是正确的;出于类似但不太严重的原因,我不喜欢 if(foo != NULL)if(foo == NULL) 的指针;因为这不能与TRUE 相比引入错误,所以这只是一个口味问题,但是使用if(foo)if(!foo) 作为任何标量值更符合C 语言的外观和感觉 【参考方案1】:

如果您的系统提供<stdbool.h>,只需包含它。这定义了许多宏,包括boolfalsetrue(分别定义为_Bool、0 和1)。有关详细信息,请参阅 C99 的第 7.16 节。

【讨论】:

没有“bool”是宏。类型为“_Bool”。否则会严重破坏旧代码。 你可以使用_Bool而不包括stdbool.h【参考方案2】:

直接在代码中使用 0 或 1 即可。

对于 C 程序员来说,这就像真或假一样直观。

【讨论】:

对于 C 程序员,-1 也是正确的,因为它不是零。就此而言,42 和 -234 也是真实值。我已经看到 -1、-2 和其他值是真的。某些函数成功返回 0(零)。嗯,为了保持一致性。 我通常只看到 1 或 -1 用作真值。 -1 因为它是二进制的全1。我很想知道你在哪里找到 -2。 我同意托马斯的观点。 0 被用作“无错误”的错误代码(通常也用作int 类型)这一事实有时使得一个值是否应该在布尔上下文中使用变得不明显。 想想一个函数返回 0 表示没有错误,作为回答“你有什么问题吗?”这个问题。 - “0=假=否”。 int fail = close(fd); if (!fail) great(); else weep(); @squelart:问题是许多返回布尔值的函数没有这种语义,成功时返回真值,失败时返回假值。 (例如,大部分 Win32 API 都是这样设计的。)【参考方案3】:

我通常做一个:

typedef enum FALSE = 0, TRUE boolean;

【讨论】:

为什么要明确设置 FALSE=0?枚举的第一个元素不是自动为0吗? @lindelof 以防万一他们将FileNotFound 添加到该枚举的前面。 ;-) @lindelof 说得通。确保 FALSE 为 0 是唯一重要的事情。 TRUE 可以是任何东西,只要它不同。【参考方案4】:

使用 stdbool.h 定义的 bool 类型,当您需要将代码从支持 bool 类型的新编译器移动到旧编译器时会出现问题。当您使用基于旧版本规范的 C 编译器迁移到新架构时,这可能会在嵌入式编程环境中发生。

总之,当可移植性很重要时,我会坚持使用宏。否则,请按照其他人的建议执行并使用 bulit in type。

【讨论】:

【参考方案5】:

您选择三个中的哪一个,将您的变量与 FALSE 或 false 进行比较。

从历史上看,在 c 或 c++ 中将 anything 与 true (1) 进行比较是一个坏主意。只有 false 保证为零 (0)。 True 是任何其他值。 许多编译器供应商在他们的头文件中都有这些定义。

#define TRUE 1
#define FALSE 0

这导致太多人走上了花园小径。 除了chartype 之外的许多库函数在成功时返回不等于1 的非零值。有大量具有相同行为的遗留代码。

【讨论】:

我注意到与 TRUE 的比较对未初始化的变量失败。最好初始化布尔值并与 FALSE 进行比较。如果您确实需要三个值,则枚举会更好;不,是,而且不知道。将枚举初始化为不知道。不要将枚举视为布尔值。不是。【参考方案6】:

任何非零的int都是真;假是零。这样,这样的代码将继续按预期工作:

int done = 0;   // `int` could be `bool` just as well

while (!done)

     // ...
     done = OS_SUCCESS_CODE == some_system_call ();

IMO,bool 是一种被高估的类型,可能是其他语言的继承。 int 作为布尔类型工作得很好。

【讨论】:

重新“高估”:在 C++ 中,bool 是一个单独的类型,因此它可以参与函数重载,原因与 C++ 中字符常量的类型为 char 的原因大致相同。当然,这不适用于没有函数重载的 C 语言。 不,C 的问题在于它不区分布尔值和整数。 C 几乎没有损坏。整数是一组可以并行操作的布尔值。将集合作为一个整体进行评估是它们的 ORed 值。 @starblue:C99 引入了一个专用的布尔类型;如果它让您放心,您可以假装 C 在布尔上下文中自动将标量值转换为 _Bool,这是许多动态语言中的一个特性 _Bool 的好处是它允许编译器以最有效的方式存储它(一个字节,一个字,一点,等等);甚至可以让您选择在编译时确定其大小(例如在某些编译器中,您可以将 int 指定为 2 或 4 个字节,或将 long 指定为 4 或 8 个字节)。有一个处理器想要以文字的形式访问事物吗?使_Bool字长。您的处理器是否像访问单词一样容易地访问字节?使其成为一个字节以节省空间。有位访问指令吗?也许,也许不是。延续 C 不固定int 尺寸的悠久传统......【参考方案7】:

您可以测试是否在 c99 stdbool.h 中定义了 bool

#ifndef __bool_true_false_are_defined || __bool_true_false_are_defined == 0
//typedef or define here
#endif

【讨论】:

对不起,我的最后一条评论,我的 PDF 搜索工具坏了。有关__bool_true_false_are_defined 的更多信息,请参阅第 7.16 节。【参考方案8】:

我会选择 1。我没有遇到不兼容的情况,而且更自然。但是,我认为它是 C++ 而不是 C 标准的一部分。 我认为使用定义或您的第三个选项进行肮脏的黑客攻击 - 不会获得任何性能,而只会让维护代码变得痛苦。

【讨论】:

bool 是 C++ 的一部分,但 _Bool(以 bool 作为别名)现在是 C 的一部分(从 C99 开始)。 很高兴知道这一点。谢谢。 :) 我不会选择 1,因为任何非零值都是真的。因此,对于有符号数量,-1 也是正确的。 我的意思是选项 1 ... 带有 bool 类型【参考方案9】:

当我定义一个变量时,我更喜欢 (1),但在表达式中我从不比较真假,只采用 if(flag) 或 if(!flag) 或 if(ptr) 的隐式 C 定义。这就是 C 的做事方式。

【讨论】:

【参考方案10】:

我曾经使用 #define 是因为它们使代码更易于阅读,并且与使用数字 (0,1) 相比应该没有性能下降,因为预处理器会在编译之前将 #define 转换为数字。一旦应用程序运行,预处理器就不会再次出现,因为代码已经编译。

顺便说一句,应该是:

#define FALSE 0 
#define TRUE 1

请记住,-1、-2、... 2、3 等都为真。

【讨论】:

TRUE 是只写值——读取/比较等时,任何非零值都需要被视为真。 出于某种原因 TRUE 似乎通常被定义为 #define TRUE !(FALSE) @Tom - 这是因为 !1 返回 0,但 !0 返回一个真值,它可能是各种各样的数字。 #define TRUE !(FALSE) 确保 TRUE == !0 无论 !0 返回什么确切值。【参考方案11】:

我不知道你的具体情况。回到我写 C 程序的时候,我们一直使用 #2。

#define FALSE = 0
#define TRUE = !FALSE

这可能在 DOS 或基于 Intel 的处理器的外部平台下。但我过去常常同时使用 C 和 ASM 一起编写图形库和图形 IDE。我是Micheal Abrash 的忠实粉丝,并打算学习纹理映射等。反正!这不是这里问题的主题!

这是在 C 中定义布尔值最常用的形式,因为当时不存在这个头文件 stdbool.h。

【讨论】:

你可能想这样做 #define TRUE = (!(FALSE)) #define TRUE = 1 有什么好处? 首先,不要将等号 (=) 放在#define 中。其次,只有 FALSE 有定义值;零。 TRUE 是任何其他值。【参考方案12】:

没有真正的速度差异。它们对编译器来说实际上都是一样的。不同之处在于人们试图使用和阅读您的代码。

对我来说,这使得 bool、true 和 false 成为 C++ 代码中的最佳选择。在 C 代码中,有一些编译器不支持 bool(我经常需要使用旧系统),所以在某些情况下我可能会使用定义。

【讨论】:

【参考方案13】:

1 可读性最强,不兼容所有编译器。

没有任何 ISO C 编译器具有称为 bool 的内置类型。 ISO C99 编译器有一个类型_Bool,和一个类型定义为bool 的头文件。因此,如果编译器不兼容 C99(例如 VC++),兼容性只是提供您自己的头文件的一种情况。

当然,更简单的方法是将 C 代码编译为 C++。

【讨论】:

任何足够复杂的 C 代码都无法使用 C++ 编译器进行编译。如果您想使用 C++ 编译器,请编写 C++ 代码。 @Broman 我不认为复杂性与它有太大关系。相当微妙的语义差异。 C++ 更强的类型检查将发出 C 编译没有的问题诊断。在大多数情况下,可以解决这些问题,并且代码在两种语言中都有效且语义相同,并且大多数情况下结果将是更好的代码。但确实,大型(而不一定是复杂)C 代码库在未经修改的情况下不太可能编译。 确实,这并不是严格意义上的复杂性。我的意思是,大多数重要的程序都会包含一个 malloc 调用,然后你需要进行转换。如果你打算用 C++ 编译器编译它,为什么不直接编写 C++ 代码呢? @Broman 如果将其编译为 C++,它就是 C++,即使它也是有效的 C。使用 malloc() 和需要强制转换是使 C 代码 C++ 可编译的一个实例导致略微更差的 C 代码。 @Broman 此外,这是一个非常古老的答案。 VC++ 现在有更全面的 C99 支持,包括 stdbool.h。只有当你被 C90 卡住时,C++ 才真正适用,这种可能性越来越小。【参考方案14】:

我更喜欢第三种解决方案,即使用 1 和 0,因为它在您必须测试条件是真还是假时特别有用:您可以简单地将变量用于 if 参数。 如果您使用其他方法,我认为为了与其余代码保持一致,我应该使用这样的测试:

if (variable == TRUE)

   ...

代替:

if (variable)

   ...

【讨论】:

【参考方案15】:

我更喜欢使用

#define FALSE (0!=0) 
#define TRUE  (0==0)

或直接在代码中

if (flag == (0==0))  ... 

编译器会处理这个问题。我使用了很多语言,并且不得不记住 FALSE 为 0 让我很困扰;但如果必须,我通常会考虑那个字符串循环

do  ...  while (*ptr);

这让我看到 FALSE 是 0

【讨论】:

以上是关于在 C 中使用 true 和 false的主要内容,如果未能解决你的问题,请参考以下文章

在 c 中,在 bool 中,true == 1 和 false == 0?

布尔类型和三目运算符

识别 TRUE 和 FALSE 序列中最后一个 TRUE 的位置

C++ 'true' 和 'false' 关键字在 Visual C++ 6.0 中突然不是真或假

为什么是C ++中的“整数”数据类型,能够容纳“ true”或“ false;布尔值

C++C++的true和false