简体   繁体   English

#define TRUE !FALSE vs #define TRUE 1

[英]#define TRUE !FALSE vs #define TRUE 1

Putting aside the fact that since c99 the stdbool.h has existed, when defining macros to handle Boolean types in C is there any difference between the following?撇开自 c99 以来stdbool.h已经存在的事实,在C定义宏来处理布尔类型时,以下内容有什么区别吗?

#define FALSE 0

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

From the live example here , it doesn't seem to make a difference.从这里的现场示例来看,它似乎没有什么区别。 Is there a technical benefit to either option?这两种选择都有技术优势吗? (Not including the fact that the second example would work better with c++ bool objects.) (不包括第二个示例在使用 c++ bool对象时效果更好的事实。)

ISO C and C99 both define ! ISO C 和 C99 都定义了! like so.像这样。

The result of the logical negation operator !逻辑否定运算符的结果! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int .如果其操作数的值比较不等于 0,则为 0,如果其操作数的值比较等于 0,则为 1。结果的类型为 int 。 The expression !E is equivalent to (0==E).表达式 !E 等价于 (0==E)。

So !0 evaluates to 1 .所以!0评估为1 Given a standards compliant C compiler both your options will have the same result.给定符合标准的 C 编译器,您的选项将具有相同的结果。 In addition there's no runtime penalty, compilers will constant fold !0 to 1 at compile time.此外,没有运行时惩罚,编译器会在编译时不断地将!0折叠为1


If you want to take this to the logical extreme and make no assumptions about what true or false are...如果你想把这带到逻辑上的极端并且不对真假做出假设......

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

This has the advantage of always being true no matter the language.无论使用哪种语言,这都具有始终正确的优点。 For example, in shell 0 is usually considered "true" or "not an error".例如,在 shell 0 中通常被认为是“true”或“not an error”。

This sort of thing is an anachronism from a time when C did not have an agreed upon standard.在 C 没有达成一致的标准的时候,这种事情是不合时宜的。 For example, the first edition of Code Complete advocates this on page 369. When it was published back in 1993 there was a good chance your C compiler was not going to be ISO compliant and stdbool.h did not exist.例如, Code Complete 的第一版在第 369 页提倡这一点。当它于 1993 年发布时,您的 C 编译器很可能不符合 ISO 标准并且 stdbool.h 不存在。 "Code Complete" is also intended for the polyglot programmer working in many different languages. “代码完成”也适用于使用多种不同语言的多语言程序员。 Some, like shell and Lisp, define truth differently.有些,比如 shell 和 Lisp,对真理的定义不同。

There is no benefit to option 2, as ! 0选项 2 没有任何好处,因为! 0 ! 0 is guaranteed by the C standard to evaluate to 1. C 标准保证! 0计算结果为 1。

Defining TRUE in that manner is a staple of old sources, presumably in an attempt to follow the style guide that calls for avoiding "magical constants" whenever possible.以这种方式定义TRUE是旧资料的主要内容,大概是为了遵循风格指南,该指南要求尽可能避免“魔法常数”。

#define FALSE 0

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

There is no difference in the values.值没有区别。 Both 1 and !0 are constant expressions of type int with the same value, 1 (by the Standard's definition of the semantics of the ! operator). 1!0都是具有相同值1 int类型的常量表达式(根据标准对!运算符语义的定义)。

There is a possible difference in that the second definition is not properly parenthesized.可能的区别在于第二个定义没有正确加上括号。 Remember that macro expansion is performed textually.请记住,宏扩展是以文本方式执行的。 Expanding an unparenthesized macro in the middle of an expression can lead to operator precedence problems.在表达式中间扩展一个没有括号的宏会导致运算符优先级问题。 I've written up a contrived example here .我在这里写了一个人为的例子。

Since the unary !自从一元! operator has very high precedence, you're not likely to run into a problem.运算符具有非常高的优先级,您不太可能遇到问题。 The only case I can think of is if you use it as a prefix to the indexing operator.我能想到的唯一情况是,如果您将它用作索引运算符的前缀。 For example, given:例如,给定:

int arr[] = { 10, 20 };

Option 1 gives:选项 1 给出:

TRUE[arr] == 20

while option 2 gives:而选项 2 给出:

TRUE[arr] == 0

To see why, remember that array indexing is commutative (see this question and my answer , and that the indexing operator [] binds more tightly than ! .要了解原因,请记住数组索引是可交换的(请参阅此问题我的回答,并且索引运算符[]绑定比!更紧密。

The lessons here are:这里的教训是:

  1. For any macro that's intended to be used as an expression, the entire macro definition should be enclosed in parentheses -- even if you can't think of a case where it would matter.对于任何打算用作表达式的宏,整个宏定义都应该括在括号中——即使您想不出有什么重要的情况。

  2. Keep It Simple.把事情简单化。 In C, 0 is the only false value, and 1 is the canonical true value.在 C 中, 0是唯一的假值, 1是规范的真值。 (Any non-zero value is "true", but the built-in "Boolean" operators always yield 0 or 1 .) Using the ! (任何非零值都是“真”,但内置的“布尔”运算符总是产生01 。)使用! operator to define TRUE in terms of FALSE (or vice versa) is just an unnecessary complication.运算符将TRUE定义为FALSE (反之亦然)只是一种不必要的复杂化。

Use <stdbool.h> if you can.如果可以,请使用<stdbool.h> If you can't (because you're stuck with a pre-C99 compiler), I recommend this:如果你不能(因为你坚持使用 C99 之前的编译器),我建议这样做:

typedef enum { false, true } bool;

It's not quite the same as C99's _Bool / bool (conversions to this bool type aren't normalized to 0 or 1 ), but it's close enough for almost all purposes.它与 C99 的_Bool / bool不太一样(转换到这种bool类型没有标准化为01 ),但它几乎可以满足所有用途。

Not much difference.差别不大。

#define TRUE 1 has a slight advantage over #define TRUE !FALSE in that 1 is a single item unaffected by operator precedence. #define TRUE 1#define TRUE !FALSE略有优势,因为1是不受运算符优先级影响的单个项目。

!FALSE could be (!FALSE) to cope with arcane code that attempts to use ++ -- [] . -> !FALSE可以是(!FALSE)来处理试图使用++ -- [] . ->神秘代码++ -- [] . -> ++ -- [] . -> , which have higher precedence next to FALSE . ++ -- [] . -> ,在FALSE旁边有更高的优先级。

In the C language, TRUE is properly defined as (!FALSE) because while zero (0) is FALSE and FALSE is zero (0), any other value is TRUE.在 C 语言中,TRUE 被正确定义为 (!FALSE),因为零 (0) 是 FALSE,FALSE 是零 (0),任何其他值都是 TRUE。 You can use almost any variable as a boolean expression, and if it is non-zero the value of the expression is TRUE.您几乎可以将任何变量用作布尔表达式,如果它不为零,则表达式的值为 TRUE。 A NULL pointer is zero for just that reason.正是因为这个原因,NULL 指针为零。 So is the end-of-string character ('\\0').字符串结尾字符 ('\\0') 也是如此。 There is a great deal of code written to take advantage of that fact.已经编写了大量代码来利用这一事实。 Consider:考虑:

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

The copy will end when the end-of-string character is copied.当字符串结束字符被复制时,复制将结束。 This idiom is very common.这个成语很常见。 Never mind the buffer size issues.别介意缓冲区大小问题。

This is one reason why it is a bad idea to test for equality to TRUE if you do not have a modern dedicated boolean type where the only possible values are TRUE and FALSE.这就是为什么如果您没有现代专用布尔类型(其中唯一可能的值是 TRUE 和 FALSE),则测试是否等于 TRUE 是一个坏主意的原因之一。 I suggest you make it a habit to test for inequality to FALSE anyway, for safety's sake.无论如何,为了安全起见,我建议你养成测试不等式为 FALSE 的习惯。 You may not always get to work with the new and shiny.您可能并不总是能够使用新的和闪亮的。

No much difference.没有太大区别。 But I think #define TRUE 1 is better.但我认为#define TRUE 1更好。

If you use #define TRUE !FALSE :如果您使用#define TRUE !FALSE

FALSE is 0 and TRUE is all numbers expect 0. FALSE是 0, TRUE是所有数字都期望为 0。

If you use #define TRUE 1 :如果您使用#define TRUE 1

FALSE is 0 and TRUE is 1. No problem. FALSE为 0, TRUE为 1。没问题。

They are just same.他们只是一样。

  • !0 is 1 so !FALSE is 1 !01所以!FALSE1

#define TRUE !FALSE has no technical benefit at all although it existed for along time and appeared many where. #define TRUE !FALSE根本没有技术优势,尽管它存在很长时间并且出现在很多地方。

#define TRUE !FALSE can be misunderstood, one could think that TRUE represents every value which not 0 . #define TRUE !FALSE可能会被误解,人们可能认为TRUE代表每个不是0值。

  • Only 1 equals to TRUE , others values like 2 , 3 , 255 ... (which !=0 ) does not equal to TRUE只有1等于TRUE ,其他值如23255 ...(其中!=0 )不等于TRUE

To prevent this misunderstanding , many organizations require not using #define TRUE !FALSE any more or comparison to TRUE should be changed to !FALSE :为了防止这种误解,许多组织要求不再使用#define TRUE !FALSE或与TRUE比较应更改为!FALSE

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM