C에서 부울 값 사용


답변:


1049

최선에서 최악으로 :

옵션 1 (C99)

#include <stdbool.h>

옵션 2

typedef enum { false, true } bool;

옵션 3

typedef int bool;
enum { false, true };

옵션 4

typedef int bool;
#define true 1
#define false 0

설명

  • 옵션 1은 C99를 사용하고 "표준 방식"인 경우에만 작동합니다. 가능하면 이것을 선택하십시오.
  • 옵션 2, 3 및 4는 실제로 동일한 동작을합니다. # 2와 # 3은 #defines를 사용하지 않습니다. 제 생각에는 더 좋습니다.

당신이 미정이라면, 1 번으로 가십시오!


1
그들이 최악의 선택에 가장 적합한 자세히 설명 할 수 있습니까 ?
endolith

1
@endolith <stdbool.h> bool컴파일러가 선택한 정렬, 최적화 및 저장 방법 은 부울 값의 의도 된 목적에보다 적합 할 수 있습니다 int(즉, 컴파일러 는와 bool다르게 구현하도록 선택할 수 있음 int). 운이 좋으면 컴파일 타임에 엄격한 유형 검사가 발생할 수도 있습니다.
blubberdiblub

1
왜 사용 int을위한 bool? 낭비입니다. 사용하십시오 unsigned char. 또는 C의 builtin을 사용하십시오 _Bool.
신체 없음

@NoBody 더 작은 유형을 사용하면 메모리를 절약 할 수 있지만 더 빠를 수는 없습니다. 종종 작은 크기 대신 프로세서의 기본 단어 크기를 사용하는 것이 더 빠릅니다. 컴파일러가 올바르게 정렬하기 위해 비트 시프트를해야 할 수도 있습니다.
Ted Klein Bergman

240

C의 부울에 대한 몇 가지 생각 :

나는 inttypedef 또는 특별한 정의 또는 참 / 거짓 값에 대한 열거없이 평범한 부울 유형으로 일반을 사용하기에 충분히 나이가 들었습니다. 부울 상수와 비교하지 않는 아래의 제안을 따르는 경우 어쨌든 0/1 만 사용하여 플래그를 초기화해야합니다. 그러나 이러한 접근은 현대에 너무 반동적 인 것으로 간주 될 수 있습니다. 이 경우에는 반드시<stdbool.h> 최소한 표준화의 이점이 있으므로 합니다.

부울 상수가 무엇이든, 초기화에만 사용하십시오. 절대로 같은 것을 쓰지 마십시오

if (ready == TRUE) ...
while (empty == FALSE) ...

이것들은 항상 더 선명한 것으로 대체 될 수 있습니다

if (ready) ...
while (!empty) ...

이것들은 실제로 합리적이고 이해하기 쉽게 소리내어 읽을 수 있습니다.

부울 변수에 긍정적 인 이름을 지정하십시오 (예 : full대신) notfull. 후자는 쉽게 읽기 어려운 코드로 이어집니다. 비교

if (full) ...
if (!full) ...

if (!notfull) ...
if (notfull) ...

전자쌍은 자연스럽게 !notfull읽히지 만, 그대로 읽기가 어려우며,보다 복잡한 부울 식에서는 훨씬 나빠집니다.

부울 인수는 일반적으로 피해야합니다. 이와 같이 정의 된 함수를 고려하십시오

void foo(bool option) { ... }

함수 본문 내에서 인수가 의미하는 것이 매우 명확하고 편리하고 의미있는 이름이 있기 때문입니다. 그러나 통화 사이트는 다음과 같습니다

foo(TRUE);
foo(FALSE):

여기서 함수 정의 나 선언을 항상 보지 않고 매개 변수의 의미를 알 수는 없으며 부울 매개 변수를 더 추가하면 더 악화됩니다. 나도 제안한다

typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);

또는

#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }

두 경우 모두 통화 사이트는 다음과 같습니다.

foo(OPT_ON);
foo(OPT_OFF);

독자는의 정의를 방해하지 않으면 서 적어도 이해의 기회를 갖습니다 foo.


1
그리고 두 변수가 동일한 지 어떻게 비교합니까? 부울 상수를 사용하지 않는 것은 좋지만 상수가 아닌 것을 비교할 때 문제를 해결하지는 않습니다.
Baruch

저를 용서하십시오. 그러나 나는 그 질문을 이해하지 못합니다. 두 부울 변수를 동등하게 비교하는 방법을 묻고 있습니까? 그렇다면 a == b작동 하지 않습니까?
Dale Hagglund

5
@ Kenji 당신이 말하는 것은 사실이지만, 사실과 동등한 것으로 다른 값을 사용하는 것은 거의 항상 나쁜 생각이라고 생각합니다. 가정, 귀하의 예제에서 그래서 a하고 b0부터 카운트, 내가 권하고 싶습니다 a > 0 == b > 0대신. 0이 아닌 임의의 값의 진실성을 이용한다고 주장하면와 !!var같은 부울 0/1 값을 생성 var하므로 글을 쓸 수 !!a == !!b는 있지만 독자는 다소 혼란 스럽습니다.
데일 해글 런드

3
!a == !b또한 동등성을 테스트하기에 충분하며, 0이 아닌 값은 0이되고 0은 1이됩니다.
ryanpattison

5
@rpattiso 물론 그렇습니다. 그러나 !!a"부울이 아닌 값을 동등한 값 !a으로 변환"으로 읽는 반면 "부울 변수 a를 논리적으로 반전"으로 읽는 것 같습니다 . 특히 논리적 반전이 필요한 특정 이유를 찾고 싶습니다.
Dale Hagglund


74

내가 사용한 버전은 다음과 같습니다.

typedef enum { false = 0, true = !false } bool;

false는 하나의 값만 갖지만 논리적 true는 많은 값을 가질 수 있지만 기술은 true를 컴파일러가 false와 반대로 사용할 것으로 설정합니다.

이것은 누군가가 다음과 같은 것을 코딩하는 문제를 처리합니다.

if (true == !false)

나는 이것이 좋은 습관이 아니라는 것에 동의 할 것이지만, "true =! false"를 수행하는 한 번의 비용으로 그 문제를 제거합니다.

[편집] 결국 나는 사용했다 :

typedef enum { myfalse = 0, mytrue = !myfalse } mybool;

정의 true하고 있던 다른 체계와 이름 충돌을 피하기 위해false . 그러나 개념은 동일합니다.

[편집] 정수를 부울로 변환하는 방법 :

mybool somebool;
int someint = 5;
somebool = !!someint;

첫 번째 (가장 오른쪽)! 0이 아닌 정수를 0으로 변환 한 다음 두 번째 (가장 왼쪽)! 0을 myfalse값으로 변환합니다 . 독자가 제로 정수를 변환하는 연습으로 남겨 두겠습니다.

[편집] 기본값이 같더라도 특정 값이 필요할 때 열거 형에 값을 명시 적으로 설정하는 것이 내 스타일입니다. 예 : false는 0이어야하기 때문에 false = 0,대신 사용하십시오.false,


5
또한 열거 형을 사용하는 또 다른 이점은 IDE 통합이다 - true, falsebool강조 표시됩니다 대부분의 IDE의 그들은 반대로 열거 값과 타입 정의, 때문에 #defines거의 이제까지 구문 강조 표시됩니다.

호기심 : 실제로 작동하는지 여부를 무시하고 열거 형이 동일한 열거 형 의 이전 값을 참조 할 수 있도록 유효한 C (99+) 입니까?

@ tgm1024 gcc -ansi -pedantic -Wall는 경고를 제공하지 않으므로 신뢰합니다 gcc. 이것이 효과가 있다면 c89잘 작동합니다 c99.
yyny

1
"false에는 하나의 값만 있기 때문에 논리적 인 true에는 많은 값이있을 수 있지만 기술은 true를 컴파일러가 false와 반대로 사용할 것입니다." 부정 연산자는 !단지 값을 반환 할 수 있습니다 01그래서 true = !false항상 할당 값 1이 방법은 여분의 안전을 이상 제공하지 않습니다 것입니다 typedef enum { false, true } bool;.
user694733

1
내가 찾은 것은 C90 (6.3.3.3 단항 산술 연산자)입니다. "피연산자의 값이 0과 같지 않으면 논리 부정 연산자!의 결과는 0입니다. 피연산자의 값이 0과 비교하면 1입니다. 결과의 형식은 int입니다.! E 식은 (O == E)와 같습니다. " 이는 표준 C를 지원한다고 주장한 모든 컴파일러를 포괄해야합니다. 컴파일러는 관찰 가능한 동작 (예 : 등 if(!value))에 중요하지 않은 경우이 규칙을 법적으로 무시할 수 있지만이 경우에는 예외가 적용되지 않습니다.
user694733


30

먼저 첫 번째 것들. C, 즉 ISO / IEC 9899는 현재 19 년 동안 부울 유형이었습니다 . 이 질문을 방문 할 때 아마추어 / 학술 / 전문 부품이 결합 된 C 프로그래밍 경력 의 예상 시간보다 더 긴 시간 입니다. 광산은 아마도 1-2 년 정도를 능가합니다. 그것은 평균적인 독자가 C에 대해 전혀 아무것도 배우지 않았을 때 C는 실제로 부울 데이터 유형을 가졌음을 의미합니다 .

데이터 유형에 대해서는 #include <stdbool.h>, 사용 true, falsebool. 아니면, 사용에 포함되지 않습니다 _Bool, 1그리고 0대신합니다.


이 스레드에 대한 다른 답변에서 다양한 위험한 관행이 촉진됩니다. 나는 그것들을 다룰 것이다 :

typedef int bool;
#define true 1
#define false 0

19 년 이내에 C를 배운 캐주얼 리더 bool실제 bool 데이터 유형을 참조하고 비슷하게 동작 할 것으로 예상 하지만 그렇지 않습니다! 예를 들어

double a = ...;
bool b = a;

C99으로 bool/ _Bool, b에 설정됩니다 false IFF는 a 제로이었다 true그렇지. C11 6.3.1.2p1

  1. 스칼라 값이로 변환 될 때 값이 _Bool0과 비교되면 결과는 0입니다. 그렇지 않으면 결과는 1입니다. 59)

각주

59) NaN은 0과 같지 않으므로 1로 변환됩니다.

으로 typedef장소에서의이 double강제 변환 될 수 int의 두 배의 값이 범위 내에없는 경우는 - int1, 행동이 정의되어 있지 않습니다 .

if truefalse에 선언 된 경우에도 동일하게 적용됩니다 enum.

무엇 짝수 더 위험한를 선언한다

typedef enum bool {
    false, true
} bool;

지금 때문에 모든 값이 1과 0 이외의 무효이고, 이러한 값은 해당 유형의 변수에 할당되어야 동작은 전체적으로 정의되지 않을 것이다 .

따라서 부적합한 변수에 대해 설명 할 수없는 이유로 C99를 사용할 수없는 경우 다음을 사용해야합니다.

  • 입력 int01 같은 -입니다 ; 이중 부정을 사용하여 다른 값에서이 값으로 도메인 변환을 신중하게 수행!!
  • 또는 당신이 경우 주장 은 0, falsy 0이 아닌 truish 것을 기억하지 않는 이상 사용에서 대문자 그들이 C99 개념과 혼동되지 않도록하는 것이 : BOOL, TRUEFALSE!

1
C 표준의 어떤 부분이 열거 된 유형의 객체가 명시 적으로 나열된 값을 보유하도록 제한합니까? 열거 된 상수의 가장 큰 값이 UCHAR_MAX 또는 USHRT_MAX보다 작은 경우 구현 에서 열거 형보다 작 int거나 유형 unsigned int을 유지할 수 있지만 표준에서 열거 형이 정수 이외의 것으로 작동하는 것을 아는 것은 없습니다. 유형.
supercat

18
typedef enum {
    false = 0,
    true
} t_bool;

2
2에서 MAX_INT까지도 true로 평가되어야합니다.
technosaurus

2
@technosaurus! false는 0이 아닌 숫자 일 수 있으므로이 방법을 사용한다고! false == true를 보장하지는 않습니다. 간단한 해결 방법은! false에 true를 명시 적으로 지정하는 것입니다.
Andrew

3
@Andrew 사실이 아닙니다. !0 = 1C 표준에 의해 그리고 !a = 0임의의 비 - 제로 값 a. 문제는 0이 아닌 모든 것이 참으로 간주된다는 것입니다. 따라서 aand b가 둘 다 "true"인 경우 반드시`a == b` 인 것은 아닙니다.
Jeremy West

14

C는 부울 타입입니다 : bool (최근 10 (!) 년 동안)

stdbool.h를 포함하면 true / false가 예상대로 작동합니다.


12
표준에서는 10 년이지만 컴파일러에서는 10 년이 아닙니다! MSVC ++의 C 컴파일은 // 주석을 허용하는 것 외에는 C99를 전혀 지원하지 않으며, 그렇게 할 가능성도 없습니다. 또한 _Bool은 C99에서 내장 유형으로 정의되는 반면 bool은 <stdbool.h> 헤더의 typedef입니다.
Clifford

5
@Clifford 댓글 4 년 후 ... 아무것도 변경되지 않았습니다. MSVC는 C ++ 컴파일러이며 MS가 모든 새로운 C 기능 (C99 및 C11)을 지원하는 데 열중하지 않다고 말한 것으로 생각합니다. 그러나 MSVC가 새로운 C 기능을 이유 (특히 10 년 동안 대답 할 때)로 지원하지 않는다는 사실을 알 수 없습니다 . 프로그래밍 세계에서 10 년은 정말 오랜 시간입니다. 괜찮은 컴파일러라면 벤더가 지원할 계획이라면 10 년 이내에 지원해야합니다.
PP

2
@ KingsIndian : 왜 당신이 나에게 당신의 의견을 지시했는지 또는 전혀 의견을 말할 필요성을 느꼈습니다. 나는 글을 쓰는 시점에 서서 상황을 말하고 있었다. 나는 그 상황을지지하지 않고 단지 "답변"이 모든 상황에 적용되지 않을 수도 있다고 지적했다.
Clifford

@Clifford : 엄밀히 말하면 표준은 bool로 확장되는 매크로 여야합니다 _Bool. #undef매크로는 가능하지만 (최소한 과도 측량으로는 허용되지만) untypedeftypedef 는 불가능 하기 때문에 차이점이 중요합니다 . 그러나 첫 번째 의견의 주요 추력은 변경되지 않습니다.
Jonathan Leffler

2
VS2015 이상 (및 이전의 시점까지)은 C 컴파일 을 bool통한 문제에 아무런 문제가 없습니다 <stdbool.h>. 로 해결됩니다 _Bool.

11

부울 연산에서 0이 아닌 것은 true로 평가되므로

#define TRUE 1
#define FALSE 0

상수를 사용하십시오.


10
그러나 실제 결과는 0이 아닌 값일 수 있으므로 다른 언어와 동등한 if (t == TRUE) {...} 및 if (t) 테스트는 C에서 동일하지 않습니다. .
Fortega

1
당신 말이 맞지만 C ++에서도 부울 유형이 있습니다. ... 내가 5837834939의 값을 부울 변수를 본 적이 디버깅시
ggambett을

1
C ++에서 if (t == true) 테스트는 if (t) 테스트와 같습니다. C ++는 일부 변환을 수행하기 때문에 (0이 아니거나 널 포인터 값이 모두 true로 변환 됨)
Fortega

6
부울 true 값에 대해 가정해야 할 것은 0이 아닌 것입니다. 따라서 if (b)와 같은 코드는 안전하지만 if (b == TRUE)는 안전하지 않습니다. 후자는 나쁜 습관이다.
Clifford

5

C99를 사용할 수 있다면 다른 답변과 설명을 보완합니다.

+-------+----------------+-------------------------+--------------------+
|  Name | Characteristic | Dependence in stdbool.h |        Value       |
+-------+----------------+-------------------------+--------------------+
| _Bool |   Native type  |    Don't need header    |                    |
+-------+----------------+-------------------------+--------------------+
|  bool |      Macro     |           Yes           | Translate to _Bool |
+-------+----------------+-------------------------+--------------------+
|  true |      Macro     |           Yes           |   Translate to 1   |
+-------+----------------+-------------------------+--------------------+
| false |      Macro     |           Yes           |   Translate to 0   |
+-------+----------------+-------------------------+--------------------+

내 취향 중 일부 :

  • _Bool또는 bool? 둘 다 괜찮지 만 bool키워드보다 좋아 보입니다._Bool .
  • bool및에 허용되는 값 _Bool: false또는 true. 할당 0또는 1대신 false또는 true유효하지만 논리 흐름을 읽고 이해하기가 어렵습니다.

표준의 일부 정보 :

  • _BoolNOT unsigned int은 아니지만 그룹 부호없는 정수 유형의 일부입니다 . 값을 보유 할만큼 크 0거나1 .
  • DO NOT하지만, 그래, 당신은 다시 정의 할 수 있습니다 bool truefalse 확인 좋은 생각이 아니다하지만. 이 기능은 폐기 된 것으로 간주되어 향후 제거 될 예정입니다.
  • 할당 스칼라 형 으로 (연산 종류 및 포인터 유형) _Bool또는 bool경우 생성, 스칼라 값과 동일 0또는 비교 0가있을 것 0, 달리 결과는 1: _Bool x = 9; 9으로 변환되는 1지정된 때x .
  • _Bool1 바이트 (8 비트)이며 일반적으로 프로그래머는 다른 비트를 사용하려고 시도하지만 권장되지는 않습니다 char.8 비트가있는 유형 과는 달리 하나의 비트 만 사용하여 데이터를 저장 하는 것입니다. 사용 가능한 비트.

2

이것입니다 :

#define TRUE 1
#define FALSE 0

7
ID는 #define TRUE! FALSE와 같은 것을 사용합니다
Tom

2

char 또는 다른 작은 숫자 컨테이너를 사용할 수 있습니다.

의사 코드

#define TRUE  1
#define FALSE 0

char bValue = TRUE;

또한 C에서는 일반적으로 int이며 int를 사용하는 다른 코드에 의해 정밀 경고가 손실 될 수 있습니다.
Thomas Bonini

공간을 수동으로 최적화하지 않는 한 하드웨어의 일반적인 단어 크기 (예 : 일반적으로 int) 를 사용하는 것이 좋습니다 . 일부 아키텍처에서는 이러한 변수에 대한 검사를 풀고 / 마스크해야하므로 성능이 크게 저하되기 때문입니다.
Kingsley

2

_Bool을 사용할 수 있지만 리턴 값은 정수 여야합니다 (true의 경우 1, false의 경우 0). 말했다 그러나 ++ 포함 및 C로 사용 부울 것을 추천 이 회신 에서 daniweb 포럼 뿐만 아니라, 이 대답 이 다른 유래 질문에서 :

_Bool : C99의 부울 형식입니다. bool, true 또는 false에 대한 매크로를 이미 정의한 레거시 코드를 유지 관리하는 경우에만 _Bool을 직접 사용하는 것이 좋습니다. 그렇지 않으면 해당 매크로가 헤더에서 표준화됩니다. 해당 헤더를 포함하면 C ++에서와 마찬가지로 bool을 사용할 수 있습니다.


2

조건식은 0이 아닌 경우 참으로 간주되지만 C 표준에서는 논리 연산자 자체가 0 또는 1을 반환해야합니다.

@Tom : #define TRUE! FALSE는 나쁘고 완전히 무의미합니다. 헤더 파일이 컴파일 된 C ++ 코드로 들어가면 문제가 발생할 수 있습니다.

void foo(bool flag);

...

int flag = TRUE;
foo(flag);

일부 컴파일러는 int => bool 변환에 대한 경고를 생성합니다. 때때로 사람들은 다음을 수행하여 이것을 피합니다.

foo(flag == TRUE);

식을 C ++ 부울로 만듭니다. 그러나 TRUE! FALSE를 #define하면 다음과 같이 끝납니다.

foo(flag == !0);

어쨌든 경고를 유발할 수있는 int-to-bool 비교를 수행합니다.


1

C99를 사용하는 경우 _Bool유형을 사용할 수 있습니다 . #include필요 하지 않습니다. 여기서 당신은,하지만, 정수처럼 취급해야합니까 1이다 true하고 0있다 false.

그런 다음 TRUE및 을 정의 할 수 있습니다 FALSE.

_Bool this_is_a_Boolean_var = 1;


//or using it with true and false
#define TRUE 1
#define FALSE 0
_Bool var = TRUE;

또는 당신은 할 수 #include <stdbool.h>및 사용 bool, true그리고 false표준은 당신이 원하는 것처럼.
SS Anne

1

요즘 C99 는 부울 형식을 지원하지만 필요합니다 #include <stdbool.h>.

예:

#include <stdbool.h>

int main() 
{ 
    bool arr[2] = {true, false}; 

    printf("%d\n", arr[0] && arr[1]);
    printf("%d\n", arr[0] || arr[1]);

    return 0; 
} 

산출:

0
1

0

이것이 내가 사용하는 것입니다 :

enum {false, true};
typedef _Bool bool;

_Bool C에 내장 된 형식입니다. 부울 값을위한 것입니다.


-2

#define다음과 같이 지시문을 간단히 사용할 수 있습니다 .

#define TRUE 1
#define FALSE 0
#define NOT(arg) (arg == TRUE)? FALSE : TRUE
typedef int bool;

다음과 같이 사용하십시오.

bool isVisible = FALSE;
bool isWorking = TRUE;
isVisible = NOT(isVisible);

등등


5
NOT 매크로는 괄호로 묶고 arg표현식 전체 를 괄호로 묶어야합니다 #define NOT(arg) (((arg) == TRUE) ? FALSE : TRUE). 그러나 거짓 여부를 테스트하는 것이 좋습니다 ( arg0 또는 1 대신 23 인 경우에도 정답을 제공 할 것 #define NOT(arg) (((arg) == FALSE) ? TRUE : FALSE)입니다.). 그러나 전체 표현 #define NOT(arg) (!(arg))은 물론 같은 결과를 산출 할 수 있습니다.
Jonathan Leffler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.