据我所知,在C语言中使用布尔值有三种方法
对于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的价值时,前者才是正确的。后者适用于任何非零值。
- +1@devon,大多数时候我只使用常量作为返回值。
- 我建议不要定义特殊的布尔宏;这只会诱使初学者编写像if(foo == TRUE)或if(foo == FALSE)这样的东西,这在大多数语言中是一种暴行,但在C语言中更是如此,在C语言中,任何标量值!= 0在布尔上下文中都被认为是正确的;由于相似但不太严重的原因,我不喜欢if(foo != NULL)和d if(foo == NULL)表示指针;因为这不能引入bug来与TRUE表示指针相比,这只是一个品味问题,但是使用if(foo)和if(!foo)表示任何数量值更符合C语言的外观和感觉。
- stackoverflow.com/questions/1921539/在-‌&8203;c中使用布尔值
- "什么是最好的…"总是主观的,而且太容易争论而不冒风险。我编辑了问题文本以提供帮助,但即使这样也不安全。最后,我和詹姆斯德林在一起…
- @实际上,当常量跨编译单元边界使用时(在另一个C文件中),编译器可能会忽略这一点。优化它需要在链接后对代码进行优化,因为在当前编译单元的编译期间(链接前)无法知道该值。有什么想法编译器是如何避免这种情况的吗?
- 嗯…我不是C专家,但!(FALSE)不是逻辑否定吗?否则,如果!是位的,它将对-1进行评估,不是吗?
如果您的系统提供,只需包含。它定义了许多宏,包括bool、false和true(分别定义为_Bool、0和1)。详见C99第7.16节。
- 没有"bool"是一个宏。类型是"bool"。否则它将严重破坏旧代码。
- @洛萨:你说的完全正确,尽管我没想到有人会用我的小手叫我。-P
- 您可以使用_Bool,不包括stdbool.h。
- 我不敢相信在我之前的评论中,我拼错了技巧。哦,如果旧的评论可以编辑的话。;-)
在代码中直接使用0或1。
对于C程序员来说,这和判断对错一样直观。
- 对于C程序员来说,-1也是正确的,因为它不是零。因此,42和-234也是真正的值。我已经看到-1,-2和其他值是真的。某些函数成功返回0(零)。嗯,为了一致性就这么多了。
- 我通常只看到1或-1用作真值。-因为它都是二进制的。我很想知道你在哪儿找到的-2.
- 我同意托马斯的观点。0用作"无错误"的错误代码(通常也用作int类型)的事实有时使值是否应用于布尔上下文变得不明显。
- 考虑一个函数返回0表示没有错误,就像回答问题"你有什么问题吗?"-"0=假=否"。int fail = close(fd); if (!fail) { great(); } else { weep(); }
- @Squelart:问题是很多返回布尔值的函数没有这种语义,成功时返回真值,失败时返回假值。(例如,许多win32 API都是这样设计的。)
- 你是对的,不同的返回模式令人困惑。但是,如果最初的开发人员在第一次使用函数时使用了上面的建议(此时开发人员已经知道,或者已经阅读了返回值),那么以后的维护可能会更容易……
- 返回0以指示成功的模式是更大模式的一部分,如下所示:如果函数成功,则返回正整数值(例如,已处理字节数或已用时间等)。返回负整数表示失败。如果我们现在将此模式应用于只返回成功或失败的函数,那么只剩下-1代表失败,0代表成功。许多Linux/Unix系统调用和库函数都遵循这种模式,因此熟悉它是很好的。
- 我使用while(42)。
- 有些值不太正确,因为if (0.4)和if (abs(0.4))不同。
我通常做A:
1
| typedef enum {FALSE = 0, TRUE} boolean; |
- 为什么显式地将false设置为0?枚举的第一个元素不是自动0吗?
- @林德洛夫只是为了以防万一,他们把FileNotFound添加到枚举的前面。;-)
- @这是有道理的。确保false为0,这是唯一重要的。真理可以是任何东西,只要它是不同的。
无论你选择哪一个,都要将你的变量与错误或错误进行比较。
从历史上看,在C或C++中比较任何事物与真(1)是不好的。只有错误才保证为零(0)。真是任何其他值。nbsp;许多编译器供应商在它们的头文件中的某个地方有这些定义。nbsp;
定义真1定义假0
这使太多人沿着花园小路走。nbsp;除chartype外,许多库函数在成功时返回不等于1的非零值。有很多具有相同行为的遗留代码。
- 我注意到,与真的比较失败于未初始化的变量。最好初始化布尔值并与false进行比较。如果您真正需要三个值,则枚举更好;否、是和不知道。将枚举初始化为不知道。不要将枚举视为布尔型。不是这样。
对于stdbool.h定义的bool类型,当需要将代码从支持bool类型的较新编译器移动到较旧编译器时,会出现问题。当您使用基于旧版本规范的C编译器移动到新的体系结构时,这可能发生在嵌入式编程环境中。
总之,当可移植性很重要时,我会坚持使用宏。否则,执行其他人推荐的操作,并在类型中使用bulit。
您可以用测试bool是否在c99 stdbool.h中定义
1 2 3
| #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节。
除0以外的任何int都是真的;false是零。这样的代码可以继续按预期工作:
1 2 3 4 5 6 7
| int done = 0; // `int` could be `bool` just as well
while (!done)
{
// ...
done = OS_SUCCESS_CODE == some_system_call ();
} |
在我看来,bool是一种被高估的类型,可能是来自其他语言的遗留物。int作为布尔类型工作得很好。
- 在"C++"中,EDCOX1(2)是一个独立的类型,因此它可以参与函数重载,这与字符常量在C++中是EDCOX1,15的类型的原因相同。当然,这不适用于C,它没有函数重载。
- 不,C被破坏了,因为它不区分布尔值和整数。
- C几乎不坏。整数是一组布尔值,可以并行操作。整体评估集合是它们的"或"值。
- @starblue:c99引入了一种专用的布尔类型;如果它能让你放松思想,你可以假装c在布尔上下文中自动地将标量值转换为_Bool,这在许多动态语言中都有。
- _Bool的好处在于,它允许编译器以最有效的方式(字节、字、位、任何东西)存储它;甚至可以让您选择在编译时确定其大小(如在某些编译器中,您可以将int指定为2或4字节,或将long指定为4或8字节)。有一个处理器想要以文字的形式访问东西?使_Bool成为字的大小。您的处理器是否像字一样容易访问字节?将其设为字节以节省空间。有位访问指令吗?也许,也许不是。延续了C不确定尺寸的悠久传统…
- 我可以接受C的工作方式,但我认为不清晰地分离布尔型和整数型是一个设计错误。C++试图纠正这一点,但是由于需要与C向后兼容而受到阻碍,而在其他语言中犯同样的错误并不能使它更好。
- @Starblue不会说这是个错误。这在70年代是完全有意义的。
我更喜欢(1)在定义变量时,但在表达式中,我从不将其与真和假进行比较,只需采用if(flag)或if(if)的隐式C定义!flag)或if(ptr)。这是做事情的方法。
我要1分。我没有遇到与它不相容的情况,这更自然。但是,我认为它是C++的一部分,而不是C标准。我认为通过使用defines或第三个选项进行肮脏的黑客攻击不会获得任何性能,但只会带来维护代码的痛苦。
- bool是C++的一部分,但作为2的一部分(AECOX1〔2〕作为别名)现在是C的一部分(如C99)。
- 很高兴知道这一点。谢谢。:)
- 我不会选择1,因为任何非零值都是真的。所以对于有符号的量,-1也是正确的。
- 我是说选项1…带布尔型
我更喜欢第三种解决方案,即使用1和0,因为当必须测试条件是真是假时,它特别有用:您可以简单地为if参数使用变量。
如果您使用其他方法,我认为为了与代码的其余部分保持一致,我应该使用这样的测试:
1 2 3 4
| if (variable == TRUE)
{
...
} |
而不是:
1 2 3 4
| if (variable)
{
...
} |
1 is most readable not compatible with all compilers.
没有一个iso c编译器具有名为bool的内置类型。iso c99编译器有一个_Bool类型和一个typedef的bool类型的头。所以兼容性只是在编译器不兼容C99的情况下提供自己的头文件(例如VC++)。
当然,更简单的方法是编译你的C代码作为C++。
- 任何复杂度的C代码都不能用C++编译器编译。如果你想使用C++编译器,那么代码C++。
- @我不认为复杂性与它有多大关系,而是微妙的语义差异。C++强大的类型检查将发布C编译所没有的问题诊断。在大多数情况下,解决这类问题是可能的,并且代码在两种语言中都是有效的和语义相同的,而且在任何情况下,结果通常都是更好的代码。但事实上,大型(而非复杂)C代码库不太可能编译未修改的代码。
- 事实上,这并不是严格的复杂性。我的意思是,最重要的程序将包括一个malloc调用,然后您需要强制转换。如果你要用C++编译器编译它,为什么不直接编码C++呢?
- 如果Broman编译为C++,则它是C++,即使它也是有效的C。使用MalCube()和CaskRelp是一个实例,其中C代码C++可编译导致的C代码稍差。
- @此外,这是一个非常古老的答案。VC++现在已经有了更全面的C99支持,包括STDBOOL .H. C++除了在C90中的应用之外,仅适用于C90,这越来越不可能。
没有真正的速度差。它们对编译器来说是完全相同的。区别在于人类试图使用和阅读你的代码。
对我来说,使BoL、true和false成为C++代码中的最佳选择。在C代码中,有一些编译器不支持bool(我经常不得不使用旧系统),因此在某些情况下,我可能会使用定义。
我更喜欢使用
1 2
| #define FALSE (0!=0)
#define TRUE (0==0) |
或者直接在代码中
1
| if (flag == (0==0)) { ... } |
编译器会处理这个问题。我使用了很多语言,必须记住,false是0让我很困扰;但是如果必须这样做,我通常会想到字符串循环。
1
| do { ... } while (*ptr); |
这让我发现错误是0
我不知道你的具体情况。当我写C程序的时候,我们总是使用2。
1 2
| #define FALSE = 0
#define TRUE = !FALSE |
这可能是在外星平台下的DOS或基于Intel的处理器。但我曾经同时使用C和ASM编写图形库和图形化IDE。我是Michael Abrash的忠实粉丝,我打算学习纹理映射等。不管怎样!这不是问题的主题!
这是在C中定义布尔值最常用的形式,因为这个headerfile stdbool.h当时不存在。
- 你可能想这样做定义真=!(假)
- 与#define TRUE = 1相比有什么好处?
- 首先,不要在定义中使用等号(=)。其次,只有false有一个定义的值;零。真是任何其他值。
我以前使用define是因为它们使代码更容易阅读,而且与使用数字(0,1)相比,性能不应该下降,因为预处理器在编译前将define转换为数字。一旦应用程序运行,预处理器就不会再次出现,因为代码已经编译。
顺便说一句,应该是:
1 2
| #define FALSE 0
#define TRUE 1 |
记住-1,-2,…2、3等。所有的计算结果都为真。
- true是一个只写的值——当读取/比较等时,任何非零值都需要被视为true。
- 出于某种原因,真似乎通常被定义为定义真!(假)
- @汤姆-这是因为!1返回0,但!0返回一个真值,可以是各种各样的数字。#define TRUE !(FALSE)确保TRUE == !0不考虑!0返回的确切值。