#define TRUE!FALSE vs #define TRUE 1

撇开自从c99以来stdbool.h已经存在的事实,当定义宏来处理C布尔类型时,以下是否有任何区别?

 #define FALSE 0 #define TRUE 1 // Option 1 #define TRUE !FALSE // Option 2 

从这里的实例来看 ,它似乎没有什么区别。 两种方案都有技术优势吗? (不包括第二个例子对c ++ bool对象更好的事实。)

ISO C和C99都定义了! 像这样。

逻辑否定运算符的结果! 如果其操作数的值比较不等于0则为0;如果其操作数的值比较等于0则为1.结果的类型为int。 表达式!E等价于(0 == E)。

所以!0评估为1给定符合标准的C编译器 ,您的选项将具有相同的结果。 此外,没有运行时惩罚,编译器将在编译时不断折叠!01


如果你想把它带到逻辑极端,不做任何关于真或假的假设……

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

无论语言如何,这都具有始终如一的优点。 例如,在shell 0中通常被认为是“真”或“不是错误”。

从C没有达成一致意见的标准来看,这种事情是不合时宜的。 例如, Code Complete的第一版在第369页提倡这一点。当它在1993年发布时,你的C编译器很可能不符合ISO标准,并且stdbool.h不存在。 “代码完成”也适用于使用多种语言的多语言程序员。 有些像shell和Lisp,以不同的方式定义真理。

选项2没有任何好处,因为! 0 ! 0标准由C标准保证评估为1。

以这种方式定义TRUE是旧资源的主要内容,可能是为了遵循风格指南,要求尽可能避免“魔法常数”。

差别不大。

#define TRUE 1优于#define TRUE !FALSE1表示不受运算符优先级影响的单项。

!FALSE可以(!FALSE)来处理试图使用++ -- [] . ->神秘代码++ -- [] . -> ++ -- [] . -> ,其优先级高于FALSE

 #define FALSE 0 #define TRUE 1 // Option 1 #define TRUE !FALSE // Option 2 

价值没有区别。 1!0都是int类型的常量表达式,具有相同的值1 (通过标准对!运算符的语义的定义)。

第二个定义没有正确括号,可能存在差异。 请记住,宏扩展是以文本方式执行的。 在表达式中间展开未经表达的宏可能会导致运算符优先级问题。 我在这里写了一个人为的例子。

自一元以来! 运算符具有非常高的优先级,您不太可能遇到问题。 我能想到的唯一情况是你是否将它用作索引操作符的前缀。 例如,给定:

 int arr[] = { 10, 20 }; 

选项1给出:

 TRUE[arr] == 20 

而选项2给出:

 TRUE[arr] == 0 

要了解原因,请记住数组索引是可交换的(请参阅此问题和我的答案 ,并且索引运算符[]绑定比!

这里的课程是:

  1. 对于任何打算用作表达式的宏,整个宏定义应该括在括号中 – 即使你不能想到它会重要的情况。

  2. 把事情简单化。 在C中, 0是唯一的假值, 1是规范的真值。 (任何非零值都是“true”,但内置的“布尔”运算符总是产生01 )使用! 运算符以FALSE定义TRUE (反之亦然)只是一种不必要的复杂化。

如果可以,请使用 。 如果你不能(因为你坚持使用前C99编译器),我推荐这个:

 typedef enum { false, true } bool; 

它与C99的_Bool / bool不完全相同(对此bool类型的转换未归一化为01 ),但它几乎适用于所有目的。

在C语言中,TRUE被正确定义为(!FALSE),因为当零(0)为FALSE且FALSE为零(0)时, 任何其他值为 TRUE。 您几乎可以将任何变量用作布尔表达式,如果它不为零,则表达式的值为TRUE。 出于这个原因,NULL指针为零。 字符串结尾字符(’\ 0’)也是如此。 编写了大量代码来利用这一事实。 考虑:

 while ( *d++ = *s++ ); 

复制将在复制字符串结尾字符时结束。 这个成语很常见。 别介意缓冲区大小问题。

如果没有现代专用布尔类型,其中唯一可能的值为TRUE和FALSE,那么测试相等为TRUE是一个坏主意的原因之一。 为了安全起见,我建议你养成一个习惯,以便在不平等的情况下测试不平等。 你可能并不总是能够使用新的和有光泽的。

他们是一样的。

  • !01所以!FALSE1

#define TRUE !FALSE完全没有技术优势,虽然它一直存在并出现在很多地方。

#define TRUE !FALSE可能会被误解,可以认为TRUE代表的每个值都不是0

  • 只有1等于TRUE ,其他值如255 ……(其中!=0 )不等于TRUE

为了防止这种误解 ,许多组织要求不要使用#define TRUE !FALSE不再或者与TRUE比较应该更改为!FALSE

 // Should not if (var_bool == TRUE) { ... } //Should if (var_bool != FALSE) { ... }