Answers:
如果编译器支持,则此方法将使用实际boolean
类型(并解析为true
和false
)。(特别是C ++)
但是,最好检查一下是否正在使用C ++(通过__cplusplus
宏)并实际使用true
and false
。
在C编译器中,这等效于0
和1
。
(请注意,删除括号会由于操作顺序而导致括号破损)
boolean
类型也一样?
true
或false
。
#define TRUE true
和#define FALSE false
随时__cplusplus
被定义。
答案是可移植性。的数值TRUE
和FALSE
并不重要。什么是重要的是,像声明if (1 < 2)
的计算结果为if (TRUE)
又像声明if (1 > 2)
评估为if (FALSE)
。
诚然,在C,(1 < 2)
计算结果为1
和(1 > 2)
的计算结果为0
,这样其他人所说,有尽可能的编译器来说没有实际的区别。但是通过让编译器根据自己的规则进行定义TRUE
和定义FALSE
,可以使程序员明白其含义,并且可以保证程序和任何其他库之间的一致性(假设其他库遵循C标准...吃惊)。
一些历史
一些基本定义FALSE
为0
和TRUE
作为-1
。与许多现代语言一样,他们将任何非零值都解释为TRUE
,但是他们将布尔表达式的真实值评估为-1
。他们的NOT
操作是通过加1并翻转符号来实现的,因为这样做的效率很高。因此,“ NOT X”变为-(x+1)
。这样做的副作用是,类似的值5
计算为TRUE
,但NOT 5
计算为-6
,这也是TRUE
!发现这种错误并不有趣。
最佳实践
鉴于事实上的规则,零被解释为FALSE
,任何非零值都被解释为TRUE
,您绝对TRUE
FALSE
不应将布尔型表达式与或进行比较。例子:
if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
为什么?因为许多程序员都使用将int
s视为bool
s 的快捷方式。它们并不相同,但是编译器通常允许。因此,例如,写
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
这看起来是合法的,编译器会很乐意接受它,但是它可能并没有满足您的要求。这是因为返回的值strcmp()
就是
如果yourString == myString
<0如果yourString < myString
> 0则为0yourString > myString
因此,上面的行TRUE
仅在时返回yourString > myString
。
正确的方法是
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
要么
// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)
类似地:
if (someBoolValue == FALSE) // Redundant.
if (!someBoolValue) // Better.
return (x > 0) ? TRUE : FALSE; // You're fired.
return (x > 0); // Simpler, clearer, correct.
if (ptr == NULL) // Perfect: compares pointers.
if (!ptr) // Sleazy, but short and valid.
if (ptr == FALSE) // Whatisthisidonteven.
您通常会在生产代码中发现其中一些“不好的例子”,并且许多有经验的程序员都对它们发誓:它们可以工作,有些比其正确的替代方法还短,并且这些习语几乎是世界公认的。但是请考虑:“正确的”版本效率不低,可以保证它们是可移植的,它们甚至可以通过最严格的要求,甚至新的程序员也可以理解它们。
那不值得吗?
(1==1)
没有比1
。编译器自己的规则是C语言的规则,对于相等性和关系运算符的语义是清晰而明确的。我从未见过编译器弄错了这些东西。
strcmp
已知by 所返回的值小于,等于或大于0。它不能保证为-1、0或1,并且在野外有些平台不返回这些值以加快实现速度。因此,如果不是这样,strcmp(a, b) == TRUE
那么a > b
反向含义可能就不成立了。
(1==1)
并且1
都是int
带有值1 的type常量表达式。它们在语义上是相同的。我想您可以编写代码来迎合那些不知道这些的读者,但是它的目的是什么?
该(1 == 1)
技巧对于以TRUE
对C透明的方式进行定义很有用,但可以在C ++中提供更好的键入。如果使用方言“ Clean C”(编译为C或C ++)或编写由C或C ++程序员使用的API头文件,则相同的代码可以解释为C或C ++。
在C翻译单位中,1 == 1
与的含义完全相同1
;与... 1 == 0
具有相同的含义0
。但是,在C ++转换单元中1 == 1
具有type bool
。因此,以TRUE
这种方式定义的宏可以更好地集成到C ++中。
如何更好地集成的一个示例是,例如,如果函数foo
具有for int
和for 的重载bool
,foo(TRUE)
则将选择bool
重载。如果TRUE
仅将其定义为1
,则在C ++中将无法正常工作。foo(TRUE)
会想要int
过载。
当然,C99引入bool
,true
和false
与这些可以在头文件中使用与C99和与工作C.
然而:
TRUE
,并FALSE
作为(0==0)
和(1==0)
早C99。如果您在C和C ++混合项目中工作,并且不想使用C99,请定义小写字母true
,false
而bool
不是。
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
话虽如此0==0
,某些程序员甚至在从未打算以任何方式与C ++进行互操作的代码中都使用了这个技巧。那并没有买任何东西,这表明程序员对布尔在C语言中的工作方式有误解。
如果不清楚C ++的解释,请使用以下测试程序:
#include <cstdio>
void foo(bool x)
{
std::puts("bool");
}
void foo(int x)
{
std::puts("int");
}
int main()
{
foo(1 == 1);
foo(1);
return 0;
}
输出:
bool
int
关于评论中的问题,如何将重载的C ++函数与C和C ++混合编程相关。这些仅说明了类型差异。希望将true
常量bool
编译为C ++时的一个合理原因是进行清晰的诊断。在最高警告级别,如果我们将整数作为bool
参数传递,则C ++编译器可能会警告我们有关转换的信息。用Clean C编写代码的原因不仅是我们的代码更具可移植性(因为C ++编译器不仅理解C编译器可以理解它),而且我们可以从C ++编译器的诊断意见中受益。
TRUE
在C ++中,这两个定义完全不同并不十分明显。
#ifdef __cplusplus
更清楚地表达您的意图。
bool
,并int
没有多大关系在实践中,因为它们是隐式转换为对方(在ç实际上“相同的”,注意引号,但是)在很多情况下您确实不需要对两者进行歧义。“不多”可能太重了,“与使用模板和重载的代码相比要少得多”也许会更好。
#define TRUE (1==1)
#define FALSE (!TRUE)
相当于
#define TRUE 1
#define FALSE 0
在C中
关系运算符的结果为0
或1
。1==1
保证被评估为1
并!(1==1)
保证被评估为0
。
绝对没有理由使用第一种形式。请注意,第一种形式的效率并不差,因为在几乎所有编译器上,常量表达式都是在编译时而不是在运行时求值的。根据以下规则,这是允许的:
(C99,6.6p2)“常量表达式可以在转换过程中而不是在运行时求值,因此可以在常量可能存在的任何位置使用。”
如果您不对TRUE
和FALSE
宏使用文字,PC-Lint甚至会发出一条消息(506,恒定值布尔值):
对于C,
TRUE
应定义为1
。但是,其他语言使用的数量不是1,因此某些程序员认为这样!0
做很安全。
同样在C99中,stdbool.h
布尔宏的定义true
并false
直接使用文字:
#define true 1
#define false 0
1==1
保证被评估为1
if(foo == true)
将从错误的做法变为平淡的越野车。
(x == TRUE)
真值与x
。
除了C ++(已经提到)之外,静态分析工具还有另一个好处。编译器将消除任何效率低下的问题,但是静态分析器可以使用其自己的抽象类型来区分比较结果和其他整数类型,因此它隐式知道TRUE必须是比较的结果,并且不应假定为兼容与一个整数。
显然,C表示它们是兼容的,但是您可以选择禁止故意使用该功能来帮助突出显示错误-例如,在有人可能会感到困惑&
和的地方&&
,或者他们混淆了操作员的优先级。
if (boolean_var == TRUE)
通过扩展来捕获愚蠢的代码,if (boolean_var == (1 == 1))
这要归功于(1 == 1)
节点的增强的类型信息而成为模式if (<*> == <boolean_expr>)
。
实际的区别是没有。0
被评估为false
并被1
评估为true
。您使用布尔表达式(1 == 1
)或1
来定义的true
事实没有任何区别。他们都被评估为int
。
请注意,C标准库提供了用于定义布尔值的特定标头:stdbool.h
。
true
被评估为1
并被false
评估为0
。C不了解本机布尔类型,它们只是整数。
int
,其值为0
或1
。C不用有一个实际的布尔类型(_Bool
与宏bool
定义<stdbool.h>
,但只在C99加入,这并没有改变运营商的语义使用新的类型。
_Bool
,并<stdbool.h>
具有#define bool _Bool
。
1 == 1
评价为是正确的int
。编辑。
通常,在C编程语言中,将1定义为true,将0定义为false。因此,为什么经常看到以下内容:
#define TRUE 1
#define FALSE 0
但是,任何不等于0的数字在条件语句中也将被评估为true。因此,通过使用以下内容:
#define TRUE (1==1)
#define FALSE (!TRUE)
您可以通过使false等于不正确的值来明确表明您试图安全地工作。
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(摘自coding-guidelines.com/cbook/cbook1_1.pdf第871页)