[c] C 부울 매크로에서 단순히 1이 아닌 #define TRUE (1 == 1) 인 이유는 무엇입니까?

C에서 정의를 보았습니다.

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

이것이 필요합니까? 단순히 TRUE를 1로 정의하고 FALSE를 0으로 정의하면 어떤 이점이 있습니까?



답변

이 방법은 실제 사용 boolean(과 해결 유형 truefalse컴파일러가 지원하는 경우). (특히 C ++)

그러나, C는 ++합니다 (통해 사용 여부를 확인하는 것이 좋습니다 것 __cplusplus매크로) 실제로 사용 true하고 false.

C 컴파일러에서 이것은 0and와 동일합니다 1.
(괄호를 제거하면 작업 순서로 인해 중단됩니다.)


답변

대답은 이식성입니다. 의 숫자 값 TRUE과는 FALSE중요하지 않습니다. 무엇 입니다 중요한 것은 같은 문이 if (1 < 2)평가 if (TRUE)와 같은 문 if (1 > 2)으로 평가 if (FALSE).

C에서, 부여, (1 < 2)평가됩니다에 1(1 > 2)평가됩니다에 0다른 사람이 말했듯이, 그래서, 컴파일러에 관한 한 지금까지 한 실제적인 차이가 없습니다. 그러나 컴파일러 가 자체 규칙에 따라 정의 TRUE하고 정의하게함으로써 FALSE프로그래머에게 그 의미를 명확하게 표시 할 수 있으며 프로그램과 다른 라이브러리 내에서 일관성을 보장 할 수 있습니다 (다른 라이브러리가 C 표준을 따르는 것으로 가정하면 … 놀랐습니다).


일부 역사
몇 가지 기본 정의 FALSE0TRUE같은 -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!

왜? 많은 프로그래머들이 ints를 bools 로 취급하는 지름길을 사용하기 때문에 . 그것들은 동일하지 않지만 컴파일러는 일반적으로 그것을 허용합니다. 예를 들어 글을 쓰는 것은 합법적입니다

if (strcmp(yourString, myString) == TRUE)  // Wrong!!!

그것은 합법적으로 보이며 컴파일러는 행복하게 받아 들일 것입니다. 그러나 아마도 원하는 것을하지 않을 것입니다. 의 반환 값 strcmp()

      만약 0 yourString == myString
    <0 인 경우 yourString < myString
    > 0 인 경우yourString > myString

따라서 위의 줄은 TRUEwhen 만 반환 합니다 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.

프로덕션 코드에서 이러한 “나쁜 예”중 일부를 발견 할 수 있으며 숙련 된 프로그래머가 맹세합니다. 제대로 작동하고 일부는 (대체적으로?) 올바른 대안보다 짧으며 관용구는 거의 보편적으로 인식됩니다. 그러나 “올바른”버전은 효율성이 떨어지지 않으며 이식성이 보장되며 가장 엄격한 정보도 전달할 수 있으며 심지어 새로운 프로그래머도 이해할 수 있습니다.

그만한 가치가 없습니까?


답변

(1 == 1)트릭은 TRUEC에 투명한 방식으로 정의하는 데 유용 하지만 C ++에서 더 나은 타이핑을 제공합니다. “Clean C”(C 또는 C ++로 컴파일 됨)라는 방언으로 작성하거나 C 또는 C ++ 프로그래머가 사용할 수있는 API 헤더 파일을 작성하는 경우 동일한 코드를 C 또는 C ++로 해석 할 수 있습니다.

C 변환 단위에서 ; 1 == 1과 정확히 동일한 의미를 갖습니다 1. 와 1 == 0같은 의미 0입니다. 그러나 C ++ 변환 단위에서 1 == 1유형은 bool입니다. 따라서 TRUE매크로는 그런 식으로 C ++에 더 잘 통합됩니다.

더 나은 통합하는 방법의 예는 예를 들어 기능이있는 경우이다 foo에 대한 과부하가 int와에 대한 bool다음, foo(TRUE)선택합니다 bool과부하를. TRUE방금 정의 된 경우 1C ++에서 제대로 작동하지 않습니다. 과부하 foo(TRUE)를 원할 int것입니다.

물론, C99 도입 bool, truefalse이들은 헤더 파일에서 사용할 수있는 C99와 C.와 작업이

하나:

  • 정의의 실천 TRUEFALSE같은 (0==0)(1==0)C99 선행한다.
  • C99를 멀리하고 C90과 함께 작업해야 할 이유는 여전히 있습니다.

당신이 혼합 C 및 C ++ 프로젝트에 노력하고 있으며, C99을 원하지 않는 경우, 소문자를 정의 true, false그리고 bool대신.

#ifndef __cplusplus
typedef int bool;
#define true (0==0)
#define false (!true)
#endif

즉, 0==0일부 프로그래머는 어떤 식 으로든 C ++과 상호 운용되지 않는 코드조차도 트릭을 사용했습니다. 그것은 아무것도 사지 않으며 프로그래머가 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

오버로드 된 C ++ 함수가 혼합 C 및 C ++ 프로그래밍과 어떻게 관련되어 있는지에 대한 의견에서 의문을 제기합니다. 이들은 단지 유형 차이를 보여줍니다. C ++로 컴파일 truebool때 상수를 유지 해야하는 유효한 이유는 완전한 진단입니다. 가장 높은 경고 수준에서 C ++ 컴파일러는 정수를 bool매개 변수 로 전달하면 변환에 대해 경고 할 수 있습니다 . Clean C로 작성하는 한 가지 이유는 코드가 이식성이 높을뿐 아니라 (C 컴파일러뿐만 아니라 C ++ 컴파일러도 이해할 수 있기 때문에) C ++ 컴파일러의 진단 의견을 활용할 수 있기 때문입니다.


답변

#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) “상수 표현식은 런타임이 아닌 변환 중에 평가할 수 있으므로 상수가있는 곳이면 어디에서나 사용할 수 있습니다.”

TRUEFALSE매크로에 리터럴을 사용하지 않으면 PC-Lint에서 메시지 (506, 상수 값 부울)를 발행 합니다.

C의 경우 TRUE로 정의해야합니다 1. 그러나 다른 언어는 1 이외의 양을 사용하므로 일부 프로그래머 !0는 안전하게 재생한다고 생각합니다.

또한 C99에서 stdbool.h부울 매크로에 대한 정의 truefalse 직접 리터럴을 사용합니다 :

#define true   1
#define false  0


답변

C ++ (이미 언급 했음) 외에도 정적 분석 도구가 또 다른 이점입니다. 컴파일러는 비 효율성을 제거하지만 정적 분석기는 자체 추상 유형을 사용하여 비교 결과와 다른 정수 유형을 구별 할 수 있으므로 TRUE는 비교의 결과 여야하며 호환되지 않아야한다는 것을 암시 적으로 알고 있습니다. 정수로.

물론 C는이 호환되는지 말한다,하지만 당신은 도움이 강조 버그에 해당 기능의 의도적 인 사용을 금지하도록 선택할 수 있습니다 – 예를 들어, 누군가가 혼동이있을 수 있습니다 경우 &&&, 또는 그들의 연산자 우선 순위를 실수 한 것.


답변

실질적인 차이는 없습니다. 0로 평가 false되고 1로 평가됩니다 true. 당신이 사용하는 것이 사실 부울 식을 ( 1 == 1) 또는 1정의는 true, 어떤 차이가되지 않습니다. 그들은 둘 다 평가int .

C 표준 라이브러리는 부울 정의를위한 특정 헤더를 제공합니다 stdbool.h.


답변

우리는 TRUE가 정확한 정확한 값을 알지 못하며 컴파일러는 자체 정의를 가질 수 있습니다. 그래서 당신이 권한을 부여하는 것은 정의를 위해 컴파일러의 내부 컴파일러를 사용하는 것입니다. 프로그래밍 습관이 좋은 경우에는 항상 필요한 것은 아니지만 코딩 스타일이 좋지 않은 경우 문제를 피할 수 있습니다.

if ((a> b) == 참)

TRUE를 수동으로 1로 정의하면 TRUE의 내부 값이 또 다른 값이됩니다.