C 부울 매크로에서 단순히 1이 아닌 #define TRUE (1 == 1) 인 이유는 무엇입니까?
C에서 정의를 보았습니다.
#define TRUE (1==1)
#define FALSE (!TRUE)
이것이 필요합니까? 단순히 TRUE를 1로 정의하고 FALSE를 0으로 정의하면 어떤 이점이 있습니까?
이 방법은 실제 사용 boolean
(과 해결 유형 true
및 false
컴파일러가 지원하는 경우). (특히 C ++)
그러나, C는 ++합니다 (통해 사용 여부를 확인하는 것이 좋습니다 것 __cplusplus
매크로) 실제로 사용 true
하고 false
.
C 컴파일러에서 이것은 0
and와 동일합니다 1
.
(괄호를 제거하면 작업 순서로 인해 중단됩니다.)
대답은 이식성입니다. 의 숫자 값 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
. 많은 현대 언어와 마찬가지로, 그들은 0이 아닌 모든 값을로 해석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()
이
만약 0 yourString == myString
<0 인 경우 yourString < myString
> 0 인 경우yourString > myString
따라서 위의 줄은 TRUE
when 만 반환 합니다 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.
프로덕션 코드에서 이러한 "나쁜 예"중 일부를 발견 할 수 있으며, 숙련 된 프로그래머가 맹세합니다. 작동하고 일부는 (대체적으로?) 올바른 대안보다 짧으며 관용구는 거의 보편적으로 인식됩니다. 그러나 "올바른"버전은 효율성이 떨어지고 이식성이 보장되며 가장 엄격한 정보를 전달할 수 있으며 새로운 프로그래머도 이해할 수 있습니다.
그만한 가치가 없습니까?
The (1 == 1)
trick is useful for defining TRUE
in 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.
In C translation units, 1 == 1
has exactly the same meaning as 1
; and 1 == 0
has the same meaning as 0
. However, in the C++ translation units, 1 == 1
has type bool
. So the TRUE
macro defined that way integrates better into C++.
An example of how it integrates better is that for instance if function foo
has overloads for int
and for bool
, then foo(TRUE)
will choose the bool
overload. If TRUE
is just defined as 1
, then it won't work nicely in the C++. foo(TRUE)
will want the int
overload.
Of course, C99 introduced bool
, true
, and false
and these can be used in header files that work with C99 and with C.
However:
- this practice of defining
TRUE
andFALSE
as(0==0)
and(1==0)
predates C99. - there are still good reasons to stay away from C99 and work with C90.
If you're working in a mixed C and C++ project, and don't want C99, define the lower-case true
, false
and bool
instead.
#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif
That being said, the 0==0
trick 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.
In case the C++ explanation wasn't clear, here is a test program:
#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 true
constant to be bool
when 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 bool
parameter. 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.
#define TRUE (1==1)
#define FALSE (!TRUE)
is equivalent to
#define TRUE 1
#define FALSE 0
in C.
The result of the relational operators is 0
or 1
. 1==1
is guaranteed to be evaluated to 1
and !(1==1)
is guaranteed to be evaluated to 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."
PC-Lint will even issue a message (506, constant value boolean) if you don't use a literal for TRUE
and FALSE
macros:
For C,
TRUE
should be defined to be1
. However, other languages use quantities other than 1 so some programmers feel that!0
is playing it safe.
Also in C99, the stdbool.h
definitions for boolean macros true
and false
directly use literals:
#define true 1
#define false 0
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.
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.
The pratical difference is none. 0
is evaluated to false
and 1
is 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
.
Notice that the C standard library provides a specific header for defining booleans: stdbool.h
.
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:
if ( (a > b) == TRUE)
This could be a disaster if you mannually define TRUE as 1, while the internal value of TRUE is another one.
- 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:
#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:
#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.
'IT' 카테고리의 다른 글
Passport.js-오류 : 사용자를 세션으로 직렬화하지 못했습니다. (0) | 2020.06.04 |
---|---|
Rails 3 데이터 타입? (0) | 2020.06.04 |
C # 개체 풀링 패턴 구현 (0) | 2020.06.04 |
Javascript로 스크롤 막대 위치를 얻는 방법은 무엇입니까? (0) | 2020.06.04 |
Bash에서 길이가 0이 아닌 문자열을 테스트하십시오. [-n "$ var"] 또는 [ "$ var"] (0) | 2020.06.04 |