Programming/C, C++

[C++] if 조건문과 암시적 bool 형변환에 대해 이해하기

변화의 물결1 2025. 6. 26. 00:03

 

 

 

 

안녕하세요.

 

 C++에서 if(expression) 문은 가장 기본적인 제어문 하나입니다.

 우리는 보통 표현식(expression) 자리에 true 또는 false를 반환하는 비교 연산(i > j 등)이 알고 있습니다.

 하지만 C++의 if문은 생각보다 훨씬 유연하게 동작합니다. 그리고 바로 그 부분이 미묘한 버그의 원인이 되기도 합니다.

 

 이번 글에서는 if문의 조건식이 어떻게 평가되는지, 그리고 C++11의 explicit 키워드가  사용하기 전에 개발자들이 bool 타입에 대한 내용에 대해 재미 삼아 알아보겠습니다.

 


 

1. 숫자와 포인터도 받아주는 if문

 

 C++의 if문은 조건식의 결과가 꼭 bool 타입일 필요가 없습니다. 0이 아닌 숫자나 null이 아닌 포인터 등 참(true)으로 평가될 수 있는 모든 값이 조건 자리에 올 수 있습니다.

 

 

1) 숫자를 조건으로 사용하기

 

 아래 코드에서 i < j라는 조건이 참(true)이므로 printf 문을 실행합니다. 재밌는 점은 i < j의 실제 결괏값은 bool 타입의 true가 아니라, 정수 1이라는 점입니다.

 C++에서는 0을 false로, 그 외 모든 숫자를 true로 간주하기 때문에 정상적으로 동작합니다.

  

#include <stdio.h>

int main() {
    int i = 1;
    int j = 7;

    if (i < j) {
        printf("i < j의 결과: %d\n", i < j);
        printf("print\n");
    }
    return 0;
}

 

 

 

2) 포인터를 조건으로 사용하기

 

 문자열 리터럴(`"address"`)도 `if`문의 조건이 될 수 있습니다.

 이 경우, 문자열의 시작 주소값(포인터)이 반환되는데, 이 주소값은 nullptr가 아니므로 true로 평가되어 if문 내부의 코드가 실행됩니다.

 

#include <stdio.h>

int main() {
    if ("address") {
        printf("if print\n");
    }
    return 0;
}

 

 

 

 

2. 클래스와 연동 시 암시적 형 변환 문제요인

  

 만약 우리가 직접 만든 클래스 객체를 if문의 조건으로 사용한다면 어떻게 될까요? 이때 형 변환 연산자(conversion operator)를 사용합니다.

 

아래 IF_TEST 클래스는 bool, int, int* 세 가지 타입으로 변환될 수 있는 방법을 모두 정의했습니다.

 

#include <stdio.h>

class IF_TEST
{
private:
    static const int isStatic = 0;

public:
    operator bool() const {
        printf("operator bool() 호출됨\n");
        return true;
    }

    operator int() const {
        printf("operator int() 호출됨\n");
        return 2;
    }
    operator int* () const {
        printf("operator int*() 호출됨\n");
        return const_cast<int*>(&isStatic);
    }
};

int main() {
    IF_TEST t;
    if (t) { // 이 시점에 어떤 형 변환 연산자가 호출될까요?
        printf("if문 실행\n");
    }
    return 0;
}

 

 

 

 

 

if(t)가 실행될 때, 컴파일러는 t 객체를 bool 타입으로 변환하려고 시도합니다. IF_TEST 클래스에는 bool로 변환할 수 있는 operator bool()가 명확하게 정의되어 있으므로, 다른 변환 연산자(operator int, operator int*)보다 우선적으로 선택됩니다.

 

 즉, bool로의 변환이 가장 가까운 변환이기 때문입니다.

 만약 operator bool()가 없다면(주석 처리한다면), 컴파일러는 operator int()나 operator int*()를 이용해 bool로 변환을 시도할 수 있습니다.

 

 하지만 두 가지 이상의 변환 경로가 존재하면 어떤 것을 선택해야 할지 모호해져 컴파일 에러가 발생할 수 있습니다.

 

 바로 이 암시적 형 변환이 문제입니다. if (t) 뿐만 아니라 int val = t; 와 같이 의도치 않은 상황에서도 형 변환이 일어나 버그를 유발할 수 있습니다.

 

 

3. 결론 및 다음 이야기

 

 지금까지 C++ if문이 bool 외의 다른 타입을 조건으로 받아들이는 방식과, 클래스의 암시적 형 변환 연산자로 인해 발생할 수 있는 문제 상황을 살펴보았습니다.

 

 이러한 의도치 않은 형 변환을 막기 위해 과거 C++ 개발자들은 Safe Bool Idiom과 같은 디자인 패턴을 사용했습니다. 그리고 C++11부터는 explicit 키워드를 통해 이 문제를 간결하고 안전하게 해결할 수 있게 되었습니다.

 

 다음 글에서는 이 Safe Bool Idiom과 C++의 해법인 explicit operator bool()에 대해 조금 더 알아보겠습니다.

  

 

감사합니다.

 

 

<참고 자료>

1. C++ Understanding: 고급 Advanced 

https://www.youtube.com/playlist?list=PLrrTotxaO6khn83BjtBN-1HMDc9MZ__yt

2. Effective Modern 이펙티브 모던 C++, Book

 

 

 

반응형