C语言 为什么在 C 布尔宏中 #define TRUE (1==1) 而不是简单地为 1?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17010041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why #define TRUE (1==1) in a C boolean macro instead of simply as 1?
提问by
I've seen definitions in C
我看过 C 中的定义
#define TRUE (1==1)
#define FALSE (!TRUE)
Is this necessary? What's the benefit over simply defining TRUE as 1, and FALSE as 0?
这是必要的吗?简单地将 TRUE 定义为 1,将 FALSE 定义为 0 有什么好处?
采纳答案by SLaks
This approach will use the actual booleantype (and resolve to trueand false) if the compiler supports it. (specifically, C++)
如果编译器支持,此方法将使用实际boolean类型(并解析为true和false)。(具体来说,C++)
However, it would be better to check whether C++ is in use (via the __cplusplusmacro) and actually use trueand false.
但是,最好检查 C++ 是否正在使用(通过__cplusplus宏)并实际使用trueand false。
In a C compiler, this is equivalent to 0and 1.
(note that removing the parentheses will break that due to order of operations)
在 C 编译器中,这等效于0和1。
(请注意,由于操作顺序,删除括号会破坏它)
回答by Adam Liss
The answer is portability. The numeric values of TRUEand FALSEaren't important. What isimportant is that a statement like if (1 < 2)evaluates to if (TRUE)and a statement like if (1 > 2)evaluates to if (FALSE).
答案是便携性。的数值TRUE和FALSE并不重要。什么是重要的是,像声明if (1 < 2)的计算结果为if (TRUE)又像声明if (1 > 2)评估为if (FALSE)。
Granted, in C, (1 < 2)evaluates to 1and (1 > 2)evaluates to 0, so as others have said, there's no practical difference as far as the compiler is concerned. But by letting the compiler define TRUEand FALSEaccording to its own rules, you're making their meanings explicit to programmers, and you're guaranteeing consistency within your program and any other library (assuming the other library follows C standards ... you'd be amazed).
诚然,在 C 中,(1 < 2)评估为1并(1 > 2)评估为0,正如其他人所说,就编译器而言,没有实际区别。但是通过让编译器根据自己的规则定义TRUE并FALSE根据自己的规则,您将它们的含义向程序员明确说明,并且您保证了程序和任何其他库中的一致性(假设其他库遵循 C 标准......吃惊)。
Some History
Some BASICs defined FALSEas 0and TRUEas -1. Like many modern languages, they interpretedany non-zero value as TRUE, but they evaluatedboolean expressions that were true as -1. Their NOToperation was implemented by adding 1 and flipping the sign, because it was efficient to do it that way. So 'NOT x' became -(x+1). A side effect of this is that a value like 5evaluates to TRUE, but NOT 5evaluates to -6, which is also TRUE! Finding this sort of bug is not fun.
一些历史
一些基本定义FALSE为0和TRUE作为-1。像许多现代语言一样,它们将任何非零值解释为TRUE,但它们将为真的布尔表达式计算为-1。他们的NOT操作是通过加 1 和翻转符号来实现的,因为这样做很有效。所以 'NOT x' 变成了-(x+1). 这样做的一个副作用是,像这样的值的5计算结果为TRUE,但NOT 5计算结果为-6,这也是TRUE! 发现这种错误并不好玩。
Best Practices
Given the de factorules that zero is interpreted as FALSEand anynon-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUEor FALSE. Examples:
最佳实践
考虑到零被解释为并且任何非零值被解释为 的事实规则,您永远不应该将布尔表达式与或进行比较。例子:FALSETRUETRUEFALSE
if (thisValue == FALSE) // Don't do this!
if (thatValue == TRUE) // Or this!
if (otherValue != TRUE) // Whatever you do, don't do this!
Why? Because many programmers use the shortcut of treating ints as bools. They aren't the same, but compilers generally allow it. So, for example, it's perfectly legal to write
为什么?因为很多程序员使用了把ints 当作bools的快捷方式。它们不一样,但编译器通常允许它。所以,例如,写是完全合法的
if (strcmp(yourString, myString) == TRUE) // Wrong!!!
That lookslegitimate, and the compiler will happily accept it, but it probably doesn't do what you'd want. That's because the return value of strcmp()is
这看起来是合法的,编译器会很乐意接受它,但它可能不会做你想要的。那是因为的返回值strcmp()是
0 if yourString == myString
<0 if yourString < myString
>0 if yourString > myString
0 如果yourString == myString
<0 如果yourString < myString
>0 如果yourString > myString
So the line above returns TRUEonly when yourString > myString.
所以上面的行TRUE仅在yourString > myString.
The right way to do this is either
这样做的正确方法是
// Valid, but still treats int as bool.
if (strcmp(yourString, myString))
or
或者
// Better: lingustically clear, compiler will optimize.
if (strcmp(yourString, myString) != 0)
Similarly:
相似地:
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.
You'll often find some of these "bad examples" in production code, and many experienced programmers swear by them: they work, some are shorter than their (pedantically?) correct alternatives, and the idioms are almost universally recognized. But consider: the "right" versions are no less efficient, they're guaranteed to be portable, they'll pass even the strictest linters, and even new programmers will understand them.
您经常会在生产代码中发现其中一些“坏例子”,许多有经验的程序员都对它们发誓:它们可以工作,有些比他们的(迂腐?)正确的替代方案要短,而且这些习语几乎得到普遍认可。但请考虑:“正确”版本的效率并不低,它们保证可移植,它们甚至可以通过最严格的 linter,即使是新程序员也会理解它们。
Isn't that worth it?
那不值得吗?
回答by Kaz
The (1 == 1)trick is useful for defining TRUEin a way that is transparent to C, yet provides better typing in C++. The same code can be interpreted as C or C++ if you are writing in a dialect called "Clean C" (which compiles either as C or C++) or if you are writing API header files that can be used by C or C++ programmers.
这个(1 == 1)技巧对于以TRUE对 C 透明的方式定义很有用,但在 C++ 中提供更好的类型。如果您使用称为“Clean C”(编译为 C 或 C++)的方言编写,或者您正在编写可供 C 或 C++ 程序员使用的 API 头文件,则相同的代码可以解释为 C 或 C++。
In C translation units, 1 == 1has exactly the same meaning as 1; and 1 == 0has the same meaning as 0. However, in the C++ translation units, 1 == 1has type bool. So the TRUEmacro defined that way integrates better into C++.
在 C 翻译单元中,1 == 1与1;具有完全相同的含义。并与1 == 0具有相同的含义0。但是,在 C++ 翻译单元中,1 == 1具有类型bool. 所以以TRUE这种方式定义的宏可以更好地集成到 C++ 中。
An example of how it integrates better is that for instance if function foohas overloads for intand for bool, then foo(TRUE)will choose the booloverload. If TRUEis just defined as 1, then it won't work nicely in the C++. foo(TRUE)will want the intoverload.
它如何更好地集成的一个例子是,例如,如果函数foo具有 forint和 for的重载bool,foo(TRUE)则将选择bool重载。如果TRUE只是定义为1,那么它在 C++ 中将无法很好地工作。foo(TRUE)会想要int超载。
Of course, C99 introduced bool, true, and falseand these can be used in header files that work with C99 and with C.
当然,C99 引入了bool、true和 ,false并且这些可以用于与 C99 和 C 一起使用的头文件中。
However:
然而:
- this practice of defining
TRUEandFALSEas(0==0)and(1==0)predates C99. - there are still good reasons to stay away from C99 and work with C90.
- 这种定义
TRUEandFALSEas(0==0)和(1==0)早于 C99 的做法。 - 仍然有充分的理由远离 C99 并使用 C90。
If you're working in a mixed C and C++ project, and don't want C99, define the lower-case true, falseand boolinstead.
如果您在混合 C 和 C++ 项目中工作,并且不想要 C99,请定义小写true,false和bool。
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
That being said, the 0==0trick was (is?) used by some programmers even in code that was never intended to interoperate with C++ in any way. That doesn't buy anything and suggests that the programmer has a misunderstanding of how booleans work in C.
话虽如此0==0,一些程序员甚至在从未打算以任何方式与 C++ 互操作的代码中使用了这个技巧(是?)。这并没有买任何东西,并表明程序员对布尔值在 C 中的工作方式有误解。
In case the C++ explanation wasn't clear, here is a test program:
如果 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;
}
The output:
输出:
bool
int
As to the question from the comments of how are overloaded C++ functions relevant to mixed C and C++ programming. These just illustrate a type difference. A valid reason for wanting a trueconstant to be boolwhen compiled as C++ is for clean diagnostics. At its highest warning levels, a C++ compiler might warn us about a conversion if we pass an integer as a boolparameter. One reason for writing in Clean C is not only that our code is more portable (since it is understood by C++ compilers, not only C compilers), but we can benefit from the diagnostic opinions of C++ compilers.
关于重载 C++ 函数如何与混合 C 和 C++ 编程相关的评论中的问题。这些只是说明了类型差异。在编译为 C++ 时想要true常量的一个正当理由bool是为了干净的诊断。在最高警告级别,如果我们将整数作为bool参数传递,C++ 编译器可能会警告我们有关转换的信息。使用 Clean C 编写的一个原因不仅是我们的代码更易于移植(因为它可以被 C++ 编译器理解,而不仅仅是 C 编译器),而且我们可以从 C++ 编译器的诊断意见中受益。
回答by ouah
#define TRUE (1==1)
#define FALSE (!TRUE)
is equivalent to
相当于
#define TRUE 1
#define FALSE 0
in C.
在 C。
The result of the relational operators is 0or 1. 1==1is guaranteed to be evaluated to 1and !(1==1)is guaranteed to be evaluated to 0.
关系运算符的结果是0or 1。1==1保证被评估为1并且!(1==1)保证被评估为0。
There is absolutely no reason to use the first form. Note that the first form is however not less efficient as on nearly all compilers a constant expression is evaluated at compile time rather than at run-time. This is allowed according to this rule:
绝对没有理由使用第一种形式。请注意,第一种形式的效率并不低,因为在几乎所有编译器上,常量表达式都是在编译时而不是运行时计算的。根据此规则,这是允许的:
(C99, 6.6p2) "A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be."
(C99, 6.6p2) “常量表达式可以在翻译期间而不是运行时进行计算,因此可以在常量所在的任何地方使用。”
PC-Lint will even issue a message (506, constant value boolean) if you don't use a literal for TRUEand FALSEmacros:
如果您不使用文字 forTRUE和FALSE宏,PC-Lint 甚至会发出一条消息(506,常量值布尔值):
For C,
TRUEshould be defined to be1. However, other languages use quantities other than 1 so some programmers feel that!0is playing it safe.
对于 C,
TRUE应定义为1。但是,其他语言使用 1 以外的数量,因此一些程序员认为这!0是安全的。
Also in C99, the stdbool.hdefinitions for boolean macros trueand falsedirectly use literals:
同样在 C99 中,stdbool.h布尔宏的定义true和false直接使用文字:
#define true 1
#define false 0
回答by sh1
Aside from C++ (already mentioned), another benefit is for static analysis tools. The compiler will do away with any inefficiencies, but a static analyser can use its own abstract types to distinguish between comparison results and other integer types, so it knows implicitly that TRUE must be the result of a comparison and should not be assumed to be compatible with an integer.
除了 C++(已经提到),另一个好处是静态分析工具。编译器将消除任何低效率,但静态分析器可以使用自己的抽象类型来区分比较结果和其他整数类型,因此它隐含地知道 TRUE 必须是比较的结果,不应假定为兼容带一个整数。
Obviously C says that they are compatible, but you may choose to prohibit deliberate use of that feature to help highlight bugs -- for example, where somebody might have confuse &and &&, or they've bungled their operator precedence.
显然 C 表示它们是兼容的,但您可以选择禁止故意使用该功能来帮助突出错误——例如,有人可能混淆了&和&&,或者他们弄错了运算符优先级。
回答by capiggue
We don't know the exact value that TRUE is equal to and the compilers can have their own definitions. So what you privode is to use the compiler's internal one for definition. This is not always necessary if you have good programming habits but can avoid problems for some bad coding style, for example:
我们不知道 TRUE 等于的确切值,编译器可以有自己的定义。因此,您可以使用编译器的内部定义进行定义。如果您有良好的编程习惯,但可以避免某些不良编码风格的问题,这并不总是必要的,例如:
if ( (a > b) == TRUE)
如果 ( (a > b) == TRUE)
This could be a disaster if you mannually define TRUE as 1, while the internal value of TRUE is another one.
如果您手动将 TRUE 定义为 1,而 TRUE 的内部值是另一个值,这可能是一场灾难。
回答by Shoe
The pratical difference is none. 0is evaluated to falseand 1is evaluated to true. The fact that you use a boolean expression(1 == 1) or 1, to define true, doesn't make any difference. They both gets evaluated to int.
实际没有区别。0被评估为false并且1被评估为true。您使用布尔表达式( 1 == 1) 或1, 来定义 的true事实没有任何区别。他们都被评估为int。
Notice that the C standard library provides a specific header for defining booleans: stdbool.h.
请注意,C 标准库提供了用于定义布尔值的特定头文件:stdbool.h.
回答by Sabashan Ragavan
- List item
- 项目清单
Typically in the C Programming Language, 1 is defined as true and 0 is defined as false. Hence why you see the following quite often:
通常在 C 编程语言中,1 定义为真,0 定义为假。因此,为什么您经常看到以下内容:
#define TRUE 1
#define FALSE 0
However, any number not equal to 0 would be evaluated to true as well in a conditional statement. Therefore by using the below:
但是,在条件语句中,任何不等于 0 的数字也将被评估为真。因此,通过使用以下内容:
#define TRUE (1==1)
#define FALSE (!TRUE)
You can just explicitly show that you trying to play it safe by making false equal to whatever isn't true.
您可以通过使 false 等于任何不真实的内容来明确表明您试图安全地行事。

