我曾经在 C 中看过定义
#define TRUE (1==1)
#define FALSE (!TRUE)
这是必要的吗?与仅将TRUE定义为1和FALSE定义为0相比有什么好处?
我曾经在 C 中看过定义
#define TRUE (1==1)
#define FALSE (!TRUE)
这是必要的吗?与仅将TRUE定义为1和FALSE定义为0相比有什么好处?
该方法将使用实际的boolean
类型(并解析为true
和false
),如果编译器支持的话。(具体来说,是C++)
然而,更好的做法是检查是否正在使用C++(通过__cplusplus
宏),并实际使用true
和false
。
在C编译器中,这相当于0
和1
。(请注意,删除括号会由于运算次序而导致出错)
1==1
的结果是一个整数(int
)。(参见https://dev59.com/Gmsz5IYBdhLWcg3wwKmh 。) - Matboolean
类型吗? - SLakstrue
或 false
。 - Mat__cplusplus
被定义时将#define TRUE true
和#define FALSE false
。 - Nikos C.if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
为什么?因为许多程序员使用将 int
当作 bool
的快捷方式。虽然它们并不相同,但编译器通常允许这样做。因此,例如,编写以下代码是完全合法的:
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
这看起来是合法的,编译器会欣然接受,但它可能不做你想要的事情。这是因为 strcmp()
的返回值是:
当yourString == myString
时,返回0
当yourString < myString
时,返回<0
当yourString > myString
时,返回>0
所以上面的语句仅在 yourString > myString
时返回 TRUE
。
正确的方法是:
// 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语言的规则,关于相等和关系运算符的语义是明确无误的。我从未见过编译器在这些方面出现错误。 - Keith Thompsonstrcmp
返回的值被认为小于、等于或大于 0。它不能保证是 -1、0 或 1,并且有些平台不返回这些值以获得更快的实现速度。因此,如果 strcmp(a, b) == TRUE
,则 a > b
,但反向蕴含可能不成立。 - Maciej Piechotka(1==1)
和1
都是类型为int
且值为1的常量表达式。它们在语义上是相同的。我想你可以编写一些针对不知道这一点的读者的代码,但这会有何止境呢? - Keith Thompson(1 == 1)
技巧非常有用,可以定义一种对C透明的TRUE
方式,同时在C++中提供更好的类型。如果您正在编写称为“Clean C”的方言(它可以编译为C或C ++),或者编写可供C或C ++程序员使用的API头文件,则可以将相同的代码解释为C或C ++。1 == 1
与1
完全相同; 1 == 0
与0
相同。但是,在C ++翻译单元中,1 == 1
具有类型bool
。因此,以这种方式定义的TRUE
宏更好地集成到C ++中。foo
对int
和bool
进行了重载,那么foo(TRUE)
将选择bool
重载。如果TRUE
仅被定义为1
,则在C ++中不起作用。 foo(TRUE)
将需要int
重载。bool
,true
和false
,并且这些可以在与C99和C一起使用的头文件中使用。TRUE
和FALSE
定义为(0 == 0)
和(1 == 0)
的做法早于C99。true
,false
和bool
。#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
话虽如此,一些程序员甚至在从未打算与C++交互的代码中也使用了0==0
技巧。这并没有什么用处,并表明程序员对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
true
常量设置为bool
的有效原因是为了清晰的诊断信息。在最高警告级别下,如果我们将整数作为bool
参数传递,C++编译器可能会警告我们进行转换。写干净的C代码的一个原因不仅在于我们的代码更具可移植性(因为它被C++编译器理解,而不仅仅是C编译器),还在于我们可以从C++编译器的诊断意见中受益。TRUE
的两个定义不同,这一点并不明显。 - user4815162342#ifdef __cplusplus
来更清楚地表达您的意图。 - Keith Thompson(0==0)
作为定义"与语言无关的" TRUE
的适当方式,我同意使用#ifdef __cplusplus
块会更清晰。但是,尽管不是最好的方法,这个宏仍然是一种方法。唯一激发我发表评论的事情是你对重载函数示例的反应,而实际上它只是一个更本质和概念性问题的例子,即正确类型化的必要性(正如你先前的评论所暗示的那样,你也非常重视这个问题)。 - Christian Rau#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,constant value boolean):
对于C语言,应该将
TRUE
定义为1
。但是,其他语言使用的数量不是1,因此一些程序员认为!0
更为保险。
在C99中,stdbool.h
定义的布尔宏true
和false
直接使用字面值:
#define true 1
#define false 0
if(foo == true)
的代码非常重要,否则它将从不良实践变成明显的错误。 - djechlin(x == TRUE)
中的危险性与 x
可能具有不同的真值,这一点非常重要。 - Joshua Taylor除了已经提到的C++之外,另一个好处是对于静态分析工具。编译器将消除任何低效率,但静态分析器可以使用自己的抽象类型来区分比较结果和其他整数类型,因此它隐含地知道TRUE必须是比较的结果,不应假定与整数兼容。
显然,C语言说它们是兼容的,但您可能选择禁止故意使用该特性以帮助突出错误-例如,某人可能混淆了&
和&&
,或者他们已经弄乱了运算符优先级。
if (boolean_var == (1 == 1))
来捕捉愚蠢的代码if (boolean_var == TRUE)
,由于(1 == 1)
节点的增强类型信息,它会落入模式if (<*> == <boolean_expr>)
。 - Kaz0
会被解释为false
,1
会被解释为true
。使用布尔表达式(如1 == 1
)或直接使用1
来定义true
并没有区别。它们都会被解释为int
类型。stdbool.h
。true
被计算为1
,而false
被计算为0
。C语言不知道本地布尔类型,它们只是整数。 - djechlinint
,其值为0
或1
。C确实有一个实际的布尔类型(_Bool
),并且在<stdbool.h>
中定义了一个宏bool
,但这只是在C99中添加的,它没有改变运算符使用新类型的语义。 - Keith Thompson<stdbool.h>
有#define bool _Bool
。 - Keith Thompson1 == 1
被解释为int
是正确的。已编辑。 - Shoe>
运算符总是返回1表示真,0表示假。没有任何C编译器会出现这种错误。将等式与TRUE
和FALSE
进行比较是不好的风格;更清晰的写法是if (a > b)
。但是,不同的C编译器可以以不同的方式处理真和假的想法是错误的。 - Keith Thompson通常在C编程语言中,1被定义为真,0被定义为假。因此你经常会看到以下代码:
#define TRUE 1
#define FALSE 0
然而,在条件语句中,任何不等于0的数字也会被视为true。因此,通过以下方式实现:
#define TRUE (1==1)
#define FALSE (!TRUE)
#define TRUE (’/’/’/’)
;#define FALSE (’-’-’-’)
(摘自http://www.coding-guidelines.com/cbook/cbook1_1.pdf的第871页) - osgx