C 표준은 진실 값을 0 또는 1로 명시 적으로 표시합니까?


86

우리는되지 않은 번호가 동일한 것을 알고 0으로 간주됩니다 true우리가 쓸 수, C에서 :

그러나, 나는 참 /의 거짓과 같이 정의되어 있는지 궁금했다 1/ 0나는 아래의 코드를 시도하므로, C에서 :

합니까 C 표준은 명시 적으로 진리의 참 값과 거짓으로 표시 1하고 0각각을?


3
나는이 생각 SO 질문 관련
이므 란 알리

3
나는이 아래를 실행하려고 gcc함께 -std=c89하며 같은 결과를 얻을 수 있습니다.
케빈 동

1
@Blackhole, 15에서 0까지.
Arturo Torres Sánchez

6
거의 속임수이지만 SO / SE 이전 10 년 이상 : c-faq.com/bool/bool2.html .
dave_thompson_085

1
거짓이 0이라는 것은 정식이지만 참은 일반적으로 "0이 아님"으로 간주됩니다. 그러나 프로그래머는 여러 가지 이유로 1을 "0이 아닌"것으로 사용했습니다. 참이 정확히 1이라고 신뢰하지 않는 것이 좋습니다. 예제에서는 (0 == 0)이 1이지만 (12 == 12)와 같이 쉽게 값 12를 가질 수 있습니다. 또한 "true"입니다.
엔지니어

답변:


96

C 표준이 명시 적으로 진리의 값을 표시 하는가 truefalse같은 01각각을?

는 C 표준을 정의 true하고 false같은 매크로에 stdbool.h되는 확장 10각각.

C11-§7.18 :

나머지 세 개의 매크로는 #if전처리 지시문 에 사용하기에 적합 합니다. 그들은

이는 정수 상수로 확장 1,

정수 상수로 확장되는 0[...]

운영자 ==!=, 표준에 따르면

C11-§6.5.9 / 3 :

==(동일한)와 !=운영자가 자신의 낮은 우선 순위를 제외하고는 관계 연산자와 유사 (안 같음). 108) 각 연산자 1는 지정된 관계가 참이고 0거짓 이면 결과를 산출 합니다 . 결과 유형은 int입니다. 피연산자 쌍의 경우 관계 중 정확히 하나가 참입니다.


20
이 질문에 대한 것을 나에게 보인다 0 == 00 != 0등, 매크로의 값이 아닌.
MM

9
나는 그가 글을 썼을 때 true매크로가 아니라 "진정한 비교의 가치"를 의미 한다고 생각합니다true
MM

1
@KevinDong; 예, C99 초안에는 유사한 단락이 있습니다.
해킹

1
@haccks : 주저없이 "동일"하다고 말할 수 있습니다. 필요할 때마다 c99를 참조하기 때문에 단락별로 찾기에는 너무 게으 르기 때문에 귀하의 인용문을 검색했습니다. ctrl+ f;) 를 통해 검색하여 찾을 수있었습니다 .
dhein

2
@MooingDuck : NaN == NaN거짓이고 NaN != NaN참입니다. 그 진술에는 문제가 없습니다.
kennytm

51

C11에는 명시 적으로 표시되어 있지 않습니다. 모든 언어 수준 작업 은 1을 true로 반환하고 NaN을 포함하여 0이 아닌 모든 것을 true로 허용합니다.

  • 에 대해 우려하는 경우 _Bool표준에서 0과 1 만 유지하도록 요구하므로 true는 1이어야합니다 (§6.2.5 / 2).
  • 또한 <stdbool.h>매크로 true에서 1(§7.18 / 3)로 확장됩니다.
  • ==, !=, <, >, <=>=복귀 0 또는 1 (§6.5.8 / 6 §6.5.9 / 3).
  • !, &&||복귀 0 또는 1 (§6.5.3.3 / 5 / 3 §6.5.13, §6.5.14 / 3)
  • defined 0 또는 1로 확장 (§6.10.1 / 1)

그러나 모든 표준 라이브러리 함수는 예를 islower들어 진실을 위해 "0이 아닌"이라고 말하면됩니다 (예 : §7.4.1 / 1, §7.17.5.1 / 3, §7.30.2.1 / 1, §7.30.2.2.1 / 4).


§6.2.5 / 2 : 형식 _Bool으로 선언 된 개체는 값 0과 1을 저장할 수있을만큼 큽니다.

§6.5.5.3 / 5 : 논리 부정 연산자의 결과 !는 피연산자의 값이 0과 같지 않으면 0, 피연산자의 값이 0과 같으면 1입니다.…

§6.5.8 / 6 : 각 연산자 <(보다 작음), >(보다 큼), <=(작거나 같음) 및 >=(보다 크거나 같음)은 지정된 관계가 참이면 1을, 그렇지 않으면 0을 산출합니다. 거짓입니다. 107)…

§6.5.9 / 3 : ==(같음) 및 !=(같지 않음) 연산자는 더 낮은 우선 순위를 제외하고 관계 연산자와 유사합니다 .108 ) 지정된 관계가 참이면 각 연산자는 1을, 맞으면 0을 산출합니다. 그릇된. …

§6.5.13 / 3 : &&두 피연산자가 모두 0과 같지 않으면 연산자는 1을 산출합니다. …

§6.5.14 / 3 : ||연산자는 피연산자 중 하나가 0과 같지 않은 경우 1을 산출합니다. …

§6.10.1 / 1 :… 다음과 같은 경우 1로 평가되는 defined identifier-또는- 형식의 단항 연산자 표현식을 포함 할 수 있습니다 defined ( identifier ).

§7.4.1 (문자 분류 기능) / 1 :이 하위 절의 기능은 다음과 같은 경우에만 0이 아닌 (참)을 반환합니다.

§7.18 / 3 : 나머지 3 개의 매크로는 #if전처리 지시문 에 사용하기에 적합 합니다. 그들은 — true— 정수 상수 1로 확장됩니다.…

§7.17.5.1 / 3 : atomic_is_lock_free일반 함수는 객체의 작업이 잠금이없는 경우에만 0이 아닌 (true)을 반환합니다. …

§7.30.2.1 (와이드 문자 분류 기능) / 1 :이 하위 절의 기능은 다음과 같은 경우에만 0이 아닌 (참)을 반환합니다.

§7.30.2.2.1 / 4 : 다음 iswctype과 같은 경우에만 0이 아닌 값 (true)을 반환합니다.


23

C에서 부울 값 (특정 C bool/_Bool유형이 아닌 참 / 거짓 값을 의미 함)을 다룰 때 알아야 할 두 가지 표준 영역이 있습니다 .

첫 번째는 표현식 의 결과 와 관련이 있으며 C11 6.5 Expressions(예 : 관계형 및 같음 연산자) 의 다양한 부분에서 찾을 수 있습니다 . 결론은 표현식에 의해 부울 값이 생성 될 때마다 ...

... 지정된 관계가 참이면 1을, 거짓이면 0을 산출합니다. 결과는 int 유형입니다.

예, 부울 생성 식의 결과는 true의 경우 1, false의 경우 0입니다. 당신이 무엇을 찾을 것이 일치하는 stdbool.h경우 표준 매크로 truefalse같은 방식으로 정의된다.

그러나 "보내는 내용은 보수적이며 받아들이는 내용은 자유 롭다"라는 견고성 원칙 에 따라 부울 컨텍스트에서 정수 해석 이 다소 완화 된다는 점을 명심하십시오 .

다시 말하지만의 다양한 부분 6.5에서 다음과 같은 언어를 볼 수 있습니다.

||피연산자 중 하나가 있다면 1을 수득한다 연산자 0 부등 비교; 그렇지 않으면 0됩니다 . 결과는 int 유형입니다.

그 (와 다른 부분)에서, 제로 거짓으로 간주하고 있음을 분명 어떤 다른 값이 true입니다.


제쳐두고 부울 생성 및 해석에 사용되는 값을 지정하는 언어는 C99 및 C89에서도 다시 나타나므로 꽤 오랫동안 사용되었습니다. K & R (ANSI-C 두 번째 버전 첫 번째 버전) 조차도 다음과 같은 텍스트 세그먼트로이를 명시했습니다.

같은 관계식 i > j과 논리식에 의해 연결 &&하고 ||값을 갖도록 정의 1true의 경우, 및 0false입니다.

의 테스트 부분에서 if, while, for, 등, "사실은"그냥 "비 제로"를 의미한다.

&&두 피연산자 그렇지 않으면 제로 0으로 동일하지 않은 비교하면 운영자는 ... 1을 반환합니다.

||운영자는 ... 그렇지 않으면 피연산자 중 하나가 제로로 불평등 비교하면 1, 0을 반환합니다.

의 매크로는 stdbool.hC99에서도 다시 나타나지만 C89 또는 K & R에는 해당 지점에 헤더 파일이 없었기 때문에 나타나지 않습니다.


2
점에 유의 ||, ==, !=등의 수율 int이 아닌 부울 유형
MM

2
이 질문에 올바른 질문에 투표합니다. 나에게 질문은 또한 매크로가 아니라 관계 연산자에 관한 것입니다.
ckruczek

"의 테스트 부분에서 if, while, for, 등,"사실이 아닌 제로 "다만 의미한다" "." 이것은 대답의 두드러진 부분이며 제 생각에는 오래전 Dennis Ritchie의 불행한 선택입니다. 일반적으로 반환 값으로 오류 코드를 반환하는 함수를 작성한 사람 #define noErr 0과 0이 아닌 오류 코드는 오류입니다. 그리고 문제는 단순성과 아름다움이 if ( ready_to_do_something() ){do_something();} 작동하지 않는다는 것입니다. if ( !not_ready_to_do_something() ){do_something();}"거짓은 많지만 진실은 하나뿐" 이어야 합니다. TRUE는 0이어야합니다.
robert bristow-johnson

호기심에서 C 규칙의 첫 번째 초안에서 "&&"및 "||"의 동작을 지정하는 방법 피연산자에 0 또는 1이 아닌 값이있는 경우? 인용 한 텍스트는 && 및 ||로 연결된 "논리식"이라고 말합니다.하지만 이러한 연산자가 논리식 이외의 것을 연결하면 어떨까요?
supercat

1
@sdenham, 네. 내가 가지고있는 K & R 의 가장 초기 사본 (초판, 인쇄판 14, 너무 이른 것 중 하나는 PDP-11, Honeywell-6000, IBM-370 및 Interdata-8 / 32)의 하드웨어 특성에 대해 언급했습니다. A.7.6/7/10/11(관계 / 동등 / 논리 및 / 논리 또는) 모두 결과로 0 또는 1을 제공하도록 지정합니다. 그것을 포함하도록 답변을 업데이트했습니다.
paxdiablo

10

제어문, 연산자 및 부울 유형과 같은 많은 다른 것들을 혼합하고 있습니다. 각각 고유 한 규칙이 있습니다.

제어 문은 예를 들어 ifC11 6.4.8.1 문과 같이 작동합니다 .

두 형식 모두식이 0과 같지 않은 경우 첫 번째 하위 문이 실행됩니다.

while, for등 같은 규칙을 가지고있다. 이것은 "true"또는 "false"와는 관련이 없습니다.

부울 결과를 산출하는 것으로 추정되는 연산자는 실제로 int값이 1 또는 0 인을 산출하고 있습니다. 예를 들어 같음 연산자, C11 6.5.9 :

각 연산자는 지정된 관계가 참이면 1을, 거짓이면 0을 산출합니다.

위의 모든 것은 C가 1999 년까지 부울 유형을 가지지 않았기 때문이며, 하나를 얻었더라도 위의 규칙은 변경되지 않았습니다. 따라서 명령문과 연산자가 부울 유형 (예 : C ++ 및 Java)을 생성하는 대부분의 다른 프로그래밍 언어와는 달리 int값이 0이거나 0이 아닌를 생성합니다. 예를 들어, sizeof(1==1)C에서는 4를, C ++에서는 1을 제공합니다.

C의 실제 부울 유형은 명명 _Bool되며 최신 컴파일러가 필요합니다. 헤더 stdbool.h를 정의 매크로 bool, truefalse에 확장 _Bool, 10(C ++과의 호환성을 위해) 각각.


그러나 제어문과 연산자를 실제로 부울 유형이 필요하거나 산출 한 것처럼 처리하는 것은 좋은 프로그래밍 관행으로 간주됩니다. MISRA-C와 같은 특정 코딩 표준은 이러한 방법을 권장합니다. 그건:

if(ptr == NULL)대신 if(ptr).

if((data & mask) != 0)대신 if(data & mask).

이러한 스타일의 목표는 정적 분석 도구를 사용하여 유형 안전성을 높이고 버그를 줄이는 것입니다. 이 스타일은 정적 분석기를 사용하는 경우에만 의미가 있습니다. 어떤 경우에는 더 읽기 쉽고 자체 문서화 코드로 이어지지 만 예를 들어

좋습니다. 의도는 명확하고 코드는 자체 문서화입니다.

나쁜. 무엇이든 의미 할 수 c있으며 코드를 이해하려면 유형을 찾아야 합니다. 정수, 포인터 또는 문자입니까?


1
sizeof(bool)C ++의 특정 구현입니다. stackoverflow.com/questions/4897844/is-sizeofbool-defined를 참조하십시오 .
David Hammen

@DavidHammen sizeof (0 == 0)도 구현 정의 된 것처럼. 단지 예일뿐입니다.
Lundin

C가 부울 유형의 규칙을 변경했다고 생각했습니다. 다른 종류의 uintN 유형 (많은 이전 컴파일러의 "비트"유형 포함)은 값의 하위 N 비트를 저장하고 상위 비트를 무시하는 반면, 새로운 부울 유형은 모든 비트를 효과적으로 "또는"함께 "또는"합니다.
supercat

1
그게 될까요 if(ptr != NULL), 아니면 아마도 if(!ptr)?
Mathieu K.

1
if(c == '\0')코딩의 특히 일반적인 초보자 실수에 자신을 빌려주 if(c = '\0')므로 나는 그것을 피합니다. 동의 함, if(c)나쁘다 ... 예를 들면 다음과 같습니다.if(valveIsOpen)
aja

4

저는 여러 언어로 프로그래밍했습니다. 언어에 따라 true가 1 또는 -1 인 것을 보았습니다. true가 1 인 논리는 비트가 0 또는 1이라는 논리였습니다. true가 -1 인 논리는! 연산자는 1의 보완이었습니다. int에서 모든 1을 0으로, 모든 0을 1로 변경했습니다. 그래서, int의 경우,! 0 = -1 및! (-1) = 0. 이것은 내가 무언가를 == true로 비교하지 않고 대신! = false로 비교할 정도로 나를 넘어 뜨 렸습니다. 그렇게하면 내 프로그래밍 스타일이 모든 언어에서 작동합니다. 그래서 내 대답은 그것에 대해 걱정하지 않고 코드가 어느 쪽이든 올바르게 작동하도록 프로그래밍하는 것입니다.


어떻게 ! 모든 0을 1로 변경하고 여전히! 5에 대해 0을 생성합니까?
codeshot

@codeshot 할 수 없습니다. 그러나 그가 말하는 요점은 모든 언어가! 부울로. 약간의 치료! C의 ~-즉, 비트 보수입니다. 이 경우 결과 값을 결정하려면 먼저 변수의 유형을 알아야하므로! (uint32_t) 5는 4,294,967,290이됩니다. 그러나! 0은 여전히 ​​4,294,967,295이고 4,294,967,295는 사실입니다.
Pegasus Epsilon

1

이 답변은 좀 더 자세히 살펴볼 필요가 있습니다.

C ++의 실제 정의는 0이 아닌 것은 모두 참으로 취급된다는 것입니다. 이것이 왜 관련이 있습니까? C ++는 우리가 생각하는 방식으로 정수가 무엇인지 알지 못하기 때문에 우리는 그 의미를 생성하고 그것이 의미하는 바에 대한 셸과 규칙 만 가지고 있습니다. 그러나 정수를 구성하는 비트가 무엇인지 알고 있습니다.

정수로서 1은 비트 단위로 느슨하게 표현됩니다. 예를 들어 8 비트 부호있는 정수는 0000 0001입니다. 우리가 시각적으로 보는 것은 약간의 거짓말입니다. -1은 부호있는 특성 때문에 표현하는 훨씬 더 일반적인 방법입니다. '정수'의. 1은 정말 적절하다는 것을 의미 할 수 없습니다. 왜? 연산이 아니기 때문에 1111 1110입니다. 이것은 부울에 대한 정말 중요한 문제입니다. 부울에 대해 이야기 할 때는 1 비트입니다. 정말 간단합니다. 0은 거짓이고 1은 참입니다. 모든 논리 연산은 사소한 것으로 유지됩니다. 이것이 정수 (부호 있음)에 대해 '-1'을 'true'로 지정해야하는 이유입니다. 1111 1111 NOT'ed는 0000 0000이됩니다 .-- 논리가 유지되고 우리는 좋습니다. Unsigned int는 약간 까다 롭고 과거에는 훨씬 더 일반적으로 사용되었습니다. 여기서 1은 다음과 같은 논리를 암시하기 쉽기 때문에 true를 의미합니다.

그것이 설명입니다. 나는 여기에서 받아 들여지는 대답이 잘못되었다고 말합니다 .C / C ++ 정의에는 명확한 정의가 없습니다. 부울은 부울입니다. 정수를 부울로 취급 할 수 있지만 출력이 정수라는 사실은 실제로 수행되는 작업에 대해 비트 단위라는 것을 의미하지 않습니다.


4
질문은 C ++가 아니라 C에 관한 것이 었습니다.
glglgl

0

귀하의 printf진술 에서 관계 연산자 때문에 발생했습니다 .

운영자 ==및 운영자!=

때문에 (0 == 0)사실 정도 보유하고, 그것은 가치를 제공1

반면, (0 != 0)사실이 아니라면 값을 제공합니다 0.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.