#6. [레거시 C++ 가이드] BOOL과 bool
BOOL보다는 bool을 사용하라.
모던 C++
개요
Visual C++은 bool이 없던 시절부터 BOOL을 사용하여, 이전 BOOL의 잔재가 많이 남아 있습니다. BOOL 이 많이 쓰인다며 따라 쓰지 마시고, bool을 쓰세요. 그게 코딩 계약 상 안전합니다.
| 항목 | BOOL | bool | 
|---|---|---|
| 정의 | Visual C++ typedef int BOOL; | 
      C++ 표준 타입 | 
| 값 | #define TRUE 1,#define FALSE 0 | 
      true, false  | 
    
| 용량 | sizeof(BOOL) == sizeof(int) | 
      1 <= sizeof(bool) <= sizeof(long)(Visual C++ 은 1byte) | 
    
BOOL이 만들어진 이유
win32 API을 개발하던 시절에는  bool이 없어서 BOOL을 만들어 썼습니다.(C99가 되어서야 뒷북으로 bool이 들어갔데요.)
여전히 BOOL을 사용하는 변명
- 
    
이전에 사용된 코드에
BOOL이 너무 많이 있어서BOOL사용을 강제하여 어쩔 수 없습니다.(bool로 리팩토링 하세요.)BOOL을 리턴하는 함수가 있다면1
BOOL result = f();
조건 연산자를 이용하여 bool로 변환해서 써보세요. 적어도 우리가 작성하는 코드에서는
BOOL로 강제하지 않게요.1
bool result = f() ? true : false;
 - 이전 코드 리팩토링이 엄두가 안나요.(bool로 리팩토링 하세요. 오늘 시작해야 그나마 적습니다.)
 BOOL이 시스템 데이터 처리 byte 수(int)와 동일하여 bool 보다 빠릅니다.(이러한 미세한 속도조차 아쉬운 프로젝트라면, 어셈블리어를 사용하세요.)- 지독한 손맛이라 나도 모르게 
BOOL을 사용해요.(습관을 바꾸세요.) 
BOOL의 문제점
bool은 참/거짓만을 다루는 신뢰할 수 있는 코딩 계약 을 만들어 줍니다.
하지만 BOOL은 정수를 담을 수 있는 int입니다.
BOOL형 변수를 단순하게 참인지 거짓인지 비교하는데만 사용한다면, 큰 문제는 없어 보입니다.
1
2
3
4
5
BOOL b = TRUE;
EXPECT_TRUE(!b == FALSE); // !b == false이고 false를 int로 형변환하면 FALSE(0)
b = FALSE;
EXPECT_TRUE(!b == TRUE); // !b == true이고 true를 int로 형변환하면 TRUE(1)
하지만 조금만 복잡하게 논리 연산을 추가하면, 걱정이 되는 경우가 좀 생깁니다.
result1과 result2가 모두 참인 경우 진입하는 if문이 필요하다고 합시다. 간단히 && 로 조건을 만들 수 있습니다.
1
2
3
4
5
BOOL result1 = f1();
BOOL result2 = f2();
// (O) 결과가 둘다 FALSE가 아니라면 진입합니다. 믿을 수 있어요.
if (result1 && result2) {}
이번에는 둘다 참이거나, 둘다 거짓일때 진입하는 if문이 필요하다고 합시다. result1 == result2 로 검사하면 될까요?
1
2
3
// (O) 결과가 둘다 FALSE 라면 진입합니다.
// (X) 오동작. 결과가 둘다 FALSE 가 아니라면 진입할까요? 하나는 1이고, 하나는 2라면 진입 못합니다.
if (result1 == result2) {}
BOOL은 int형이라 TRUE(1)와 FALSE(0) 외에 다른 값을 가질 수 있다는 걸 상기해 보십시요. 실제로 Windows API는 0과 1외에 다른 정수값을 리턴하는 경우가 가끔 있습니다.
Windows API 의 GetMessage()를 보시면 BOOL GetMessage(...)임에도 0과 -1을 리턴합니다.
BOOL이 TRUE(1)와 FALSE(0)만 리턴한다고 신뢰하지 마십시요.
억지로 !!(!BOOL을 하면 bool로 변경되고, 원래의 참/거짓 값을 표현하기 위해 !을 한번 더함)을 붙여 bool형으로 바꿔서 검사할 수는 있습니다만, 참 보기 싫죠.
1
2
3
4
// (O) 결과가 둘다 FALSE 라면 진입합니다.
// (O) 결과 둘다 FALSE 가 아니라면 진입합니다.
// (△) 비권장. 코드가 지저분합니다. 왜 !을 2번 썼는지 끌려다니며 설명해야 합니다.
if (!!result1 == !!result2) {}
그러니
- 가독성을 위해
 true/false만 저장하는 코딩 계약 을 위해
bool을 사용하세요.
댓글남기기