“sizeof (a? true : false)”가 4 바이트의 출력을 제공하는 이유는 무엇입니까?


133

sizeof삼항 연산자를 사용 하는 연산자 에 대한 작은 코드 조각이 있습니다 .

#include <stdio.h>
#include <stdbool.h>

int main()
{
    bool a = true;
    printf("%zu\n", sizeof(bool));  // Ok
    printf("%zu\n", sizeof(a));     // Ok
    printf("%zu\n", sizeof(a ? true : false)); // Why 4?
    return 0;
}

출력 ( GCC ) :

1
1
4 // Why 4?

하지만 여기는,

printf("%zu\n", sizeof(a ? true : false)); // Why 4?

삼항 연산자는 boolean유형을 반환 하고 sizeof bool유형은 1C의 바이트입니다.

그렇다면 sizeof(a ? true : false)4 바이트의 출력을 제공합니까?


39
sizeof(true)sizeof(false)도 4 : ide.geeksforgeeks.org/O5jvuN
tkausl

7
이 구현은 "일관성은"그것은 분명히 정의 점에서 왜 여기서 더 흥미로운 질문이 될 것입니다 _Bool크기 일 수 있지만 가지고 truefalse. 그러나 표준은 내가 말할 수있는 한 그것에 대해 할 말이 없습니다.

12
@FelixPalmen 같은 이유 char a; sizeof(a) == 1sizeof('a') == sizeof(int)C가 주어진 이유 . 그것은 구현에 관한 것이 아니라 언어에 관한 것입니다.
n. '대명사'm.

10
인쇄하려고 했습니까 sizeof(true)? 아마도 얇은 부분을 좀 더 명확하게 만들 것입니다 (특히 삼항 연산자가 붉은 청어라는 것이 분명해질 것입니다).
n. '대명사'm.

4
@FelixPalmen true#defined가 1이 stdbool.h되므로 예, 이것은 리터럴 정의입니다.
n. '대명사'm.

답변:


223

당신이 있기 때문 #include <stdbool.h>입니다. 그 헤더 를 정의 매크로 true 와는 false할 수 10,이 같은 명세서의 외모 때문에 :

printf("%zu\n", sizeof(a ? 1 : 0)); // Why 4?

sizeof(int) 귀하의 플랫폼에서 4입니다.


21
"#include <stdbool.h>가 있기 때문입니다."아니요, 그렇지 않습니다. sizeof(a ? (uint8_t)1 : (uint8_t)0);또한 4의 결과에게의 정수 프로모션 줄 것 ?:피연산자하는 것은 중요한 여기 부분,하지의 크기 truefalse.
Lundin

9
@ 룬딘 : 둘 다 중요합니다. 작성된대로, 유형은 이미 int판촉이 없습니다. "수정"할 수없는 이유는 기본 프로모션입니다.
R .. GitHub 중지 지원 얼음

5
@PeterSchneider 이것은 C ++이 아닙니다. 이것은 ++ C에서 C이다, true하고 false있습니다 하지 매크로; 그것들은 키워드입니다. 이들은 1및로 정의되어 있지 0않지만 bool유형 의 참 및 거짓 값으로 정의됩니다 .
저스틴

5
@PeterSchneider 아니요, 오늘 C에 대해 배웠습니다. 두 언어를 혼동하지 마십시오. C ++에서 sizeof(true)1. demo 입니다.
Rakete1111

1
사실, 혼합했습니다. 주의 깊게 읽지 않았고 cppreference-link에 의해 오도되었습니다. 내 잘못이야, 고마워 그러나 어쨌든 C ++에 대한 느낌이 있습니다.
피터 슈나이더

66

여기서 삼항 연산자 반환 boolean유형은

좋아, 그 이상이 있습니다!

C 에서이 삼항 연산 의 결과 는 유형 int입니다. [아래 참고 사항 (1,2)]

따라서 결과는 sizeof(int)플랫폼 에서 식과 동일 합니다.


참고 1 : 인용 C11, §7.18,Boolean type and values <stdbool.h>

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

true

정수 상수 1로 확장됩니다.

false

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

참고 2 : 조건부 연산자의 경우 §6.5.15 장 ( 강조 표시 )

첫 번째 피연산자가 평가됩니다. 평가와 두 번째 또는 세 번째 피연산자 (둘 중 평가되는 것)의 평가 사이에 시퀀스 지점이 있습니다. 두 번째 피연산자는 첫 번째 피연산자가 0과 같지 않은 경우에만 평가됩니다. 세 번째 피연산자는 첫 번째 피연산자가 0과 동일한 경우에만 평가됩니다. 결과는 두 번째 또는 세 번째 피연산자 (둘 중 평가되는 것)의 값입니다. [...]

두 번째와 세 번째 피연산자 모두 산술 유형을 갖는 경우 일반적인 산술 변환에 의해 결정되는 결과 유형은 두 피연산자에 적용되었으므로 결과 유형입니다. [....]

따라서 결과는 정수 유형이며 값 범위 때문에 상수는 정확하게 유형 int입니다.

즉, 일반적인 조언 int main()int main (void)진정으로 표준을 준수하는 것이 좋습니다.


@ user694733 umm .. 왜 안되죠? <stdbool.h>MACROS를 .. 형식으로 정의합니다 int.
Sourav Ghosh

@BasileStarynkevitch 좋아, 지금, 이것은 실제로 잘못된 것 같습니다.
라브 고쉬

58

삼항 연산자는 빨간 청어입니다.

    printf("%zu\n", sizeof(true));

4를 인쇄합니다 (또는 sizeof(int)플랫폼에있는 것).

다음은 크기가 1 인 bool동의어 char또는 유사한 유형 int이며보다 큼을 가정합니다 char.

이유 sizeof(true) != sizeof(bool)와 이유 sizeof(true) == sizeof(int)는 단순히 유형의 표현 true아니기 때문 입니다bool . 유형의 표현식입니다 int. 이것은된다 #define로서 거라고 1에서 stdbool.h.

boolC 에는 유형의 r 값이 전혀 없습니다 . 에 int대한 인수로 사용되는 경우에도 이러한 모든 rvalue는 즉시로 승격 됩니다 sizeof. 편집 :이 단락은 사실이 아니며, 인수로 sizeof승격되지 않습니다 int. 이것은 결론에 영향을 미치지 않습니다.


좋은 대답입니다. 현재 가장 확고한 답변을 읽은 후 모든 진술을 4로 평가해야한다고 생각했습니다. +1
Pedro A

5
아닌가 (bool)1유형의를 rvalue bool?
벤 Voigt

printf("%u\n", sizeof((char) 1));인쇄 1하는 동안 내 플랫폼에 printf("%u\n", sizeof(1));인쇄합니다 4. 이것은 "sizeof에 대한 인수로 사용될 때에도 그러한 rvalue가 즉시 int로 승격된다"는 진술이 잘못된 것이 아닙니까?
JonatanE

이것은 실제로 질문에 대답하지 않습니다. 어쨌든 정수로 승격되기 때문에 true등 의 크기와 유형은 실제로 중요하지 않습니다 . 즉, 청어가 붉은 지에 대한 답을 제시해야합니다 . ?:int ?:
Lundin

6
대답은 가능한 가장 좋은 방법으로 문제를 해결한다고 생각합니다. 당신은 그것을 downvote 또는 개선에 오신 것을 환영합니다.
n. '대명사'm.

31

C의 부울 유형에 대해

부울 형식은 1999 년 C 언어에서 상당히 늦게 소개되었습니다. 그 전에 C에는 부울 형식이 없었지만 대신 int모든 부울 식에 사용 되었습니다. 따라서 > == !etc 와 같은 모든 논리 연산자 는 int의 값 1또는0 .

응용 프로그램에서와 같은 집에서 만든 유형을 사용하는 것은 사용자 지정이었으며 typedef enum { FALSE, TRUE } BOOL;,이 int유형 은 크기가 큰 유형으로 분류됩니다.

C ++는 bool1 바이트보다 크지 않은 훨씬 나은 명시 적 부울 형식을 가졌습니다 . C의 부울 유형 또는 표현식은 최악의 경우 4 바이트로 끝납니다. C ++와의 호환성 방식은 C에서 C99 표준으로 도입되었습니다. 그런 다음 C는 부울 유형 _Bool과 헤더를 얻습니다 stdbool.h.

stdbool.hC ++과의 호환성을 제공합니다. 이 헤더는 bool확장 가능한 매크로 (C ++ 키워드와 동일한 철자)를 정의합니다.이 _Bool정수는 1 바이트의 큰 정수형 유형입니다. 마찬가지로 헤더는 두 개의 매크로 truefalseC ++ 키워드와 같은 철자를 제공 하지만 이전 C 프로그램과의 하위 호환성을 제공 합니다. 따라서 truefalse에 확장 10C와 자신의 유형입니다int . 이러한 매크로는 실제로 해당 C ++ 키워드와 같은 부울 유형이 아닙니다.

마찬가지로, 이전 버전과의 호환성을 위해, C의 논리 연산자는 여전히 를 반환 intC는 현재 부울 타입을 가지고에도 불구하고, 오늘날까지. C ++에서 논리 연산자는을 반환합니다 bool. 따라서와 같은 표현식 은 C sizeof(a == b)의 크기를 제공 int하지만 boolC ++ 의 크기는 제공합니다 .

조건부 연산자에 대하여 ?:

조건부 연산자 ?:는 몇 가지 단점이있는 이상한 연산자입니다. 100 %에 해당한다고 생각하는 것은 흔한 실수 if() { } else {}입니다. 좀 빠지는.

첫 번째와 두 번째 또는 세 번째 피연산자의 평가 사이에는 시퀀스 지점이 있습니다. ?:에만 두번째 또는 세번째 피연산자 중 하나를 평가하는이 평가되지 않습니다 피연산자의 부작용을 실행할 수 있도록 운영자가 보장됩니다. 같은 코드 true? func1() : func2()는 실행되지 않습니다 func2(). 여태까지는 그런대로 잘됐다.

그러나 일반적인 산술 변환 을 통해 두 번째와 세 번째 피연산자가 암시 적으로 형식을 승격하고 균형을 이루어야한다는 특수 규칙이 있습니다. ( C의 암시 적 유형 승격 규칙은 여기에 설명되어 있습니다 ). 이것은 두 번째 또는 세 번째 피연산자가 항상 최소한 int.

그것은 그 문제되지 않도록 truefalse유형 될 일이 int표현은 항상 적어도의 크기를주지 않기 때문에 C에 int상관없이.

표현식을 다시 쓰더라도 여전히 !sizeof(a ? (bool)true : (bool)false) int

이는 일반적인 산술 변환을 통한 암시 적 유형 승격 때문입니다.


1
C ++은 실제로 보장하지 않습니다 sizeof(bool)==1.
aschepler 2018

1
@aschepler 아니요 그러나 C ++ 표준 이외의 실제 환경에서는이를 보장합니다. 1이 아닌 하나의 컴파일러 이름을 지정하십시오.
Lundin

안녕하세요. 나는이 대답이 첫 부분 없이 더 좋을 것이라고 생각합니다 . 두 번째 부분은 질문에 대한 답변입니다. 나머지는 흥미롭지 만 소음입니다.
YSC

@YSC 이것은 원래 C와 C ++로 태그가 지정되었으므로 서로 다른 부울 유형과 그 뒤에 숨겨진 역사를 비교해야했습니다. C ++ 태그가 아니라면 첫 번째 부분을 작성했을 것입니다. 그러나 C에서 sizeof (bool)는 1이지만 sizeof (false)는 4 인 이유를 이해해야합니다.
Lundin

21

빠른 답변 :

  • sizeof(a ? true : false)로 평가 4하기 때문에 truefalse에 정의 <stdbool.h>1하고 0, 각각에 식 팽창하므로 sizeof(a ? 1 : 0)유형의 정수 표현되는 int플랫폼에 4 바이트를 차지합니다. 같은 이유로 시스템 sizeof(true)에서도 평가 4합니다.

그러나 다음 사항에 유의하십시오.

  • sizeof(a ? a : a)또한 4삼항 연산자가 정수 표현식 인 경우 두 번째 및 세 번째 피연산자에서 정수 승격을 수행 하기 때문에 평가됩니다 . 물론 동일에 대한 발생 sizeof(a ? true : false)하고 sizeof(a ? (bool)true : (bool)false)있지만, 같은 전체 표현식 캐스팅 bool예상대로 동작합니다을 : sizeof((bool)(a ? true : false)) -> 1.

  • 또한 비교 연산자는 부울 값 1또는로 평가 0되지만 int유형은 다음과 같습니다 sizeof(a == a) -> 4.

부울 특성을 유지하는 유일한 연산자 a는 다음과 같습니다.

  • 쉼표 연산자 : 모두 sizeof(a, a)sizeof(true, a)로 평가 1컴파일시.

  • 대입 연산자 : sizeof(a = a)sizeof(a = true)의 값은 모두 입니다 1.

  • 증분 연산자 : sizeof(a++) -> 1

마지막으로 위의 모든 내용은 C에만 적용됩니다. C ++에는 bool유형, 부울 값 truefalse비교 연산자 및 삼항 연산자와 관련하여 다른 의미 가 있습니다. 이러한 모든 sizeof()표현식 1은 C ++에서 평가됩니다 .


2
피연산자가 정수로 승격 되기 때문에 실제로 어떤 유형 true과 유형이 중요하지 않다는 것을 지적하는 좋은 대답입니다 . 따라서 결과적으로 4가 산출됩니다. false?:intsizeof(a ? (uint8_t)true : (uint8_t)false)
Lundin

이 답변은 주요 중요한 포인트, 가치 int
상승

1

다음은 소스에 포함 된 스 니펫입니다.

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

매크로가 true있으며 false각각 1과 0으로 선언됩니다.

그러나이 경우 유형은 리터럴 상수의 유형입니다. 0과 1은 모두 정수에 맞는 정수 상수이므로 유형은 정수입니다.

그리고 sizeof(int)귀하의 경우는 4입니다.


-3

C에는 부울 데이터 형식이 없다, 대신 논리적 인 표현은 정수 값으로 평가 1하는 경우는 true, 그렇지 않은0 .

조건식이 좋아 if, for, while, 또는 c ? a : b수는 간주 제로가 아닌 경우, 정수를 기대하는 true특별한 경우를 제외하고, 여기 삼항 연산자가 평가하게하는 재귀 sum 함수의 true때까지 n손이 닿지 0.

int sum (int n) { return n ? n+sum(n-1) : n ;

NULL포인터 를 확인하는 데 사용할 수도 있습니다 . 여기에는 Singly-Linked-List의 내용을 인쇄하는 재귀 함수가 있습니다.

void print(sll * n){ printf("%d -> ",n->val); if(n->next)print(n->next); }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.