c++ 질문입니다.

조회수 3141회

안녕하세요.

C++ 초보자라 공부를 하다보니 이해가 안되는 부분이 있어서 질문 드립니다.

#define CHECK(condition)                                             \
  do {                                                               \
    if (UNLIKELY(!(condition))) {                                 \
      Fatal(__FILE__, __LINE__, "Check failed: %s.", #condition); \
    }                                                                \
  } while (0)

소스를 보는 중인데요. CHECK의 (condition)부분에 bool타입이 들어가기도 하고, 조건이 들어가기도 하고, 클래스가 들어가기도 하는데 해석을 어떻게 해야 하나요? CHECK(false) 이렇게 사용되면

do{
   if(UNLIKELY(!(false))) {                                 \
      Fatal(__FILE__, __LINE__, "Check failed: %s.", #condition); \
    }                                                                \
  } while (0)

이렇게 해석을 하면 되는건가요? 그리고 UNLIKELY의 경우는 다음과 같이 정의 되어있는데,

# define UNLIKELY(condition) (condition)

UNLIKELY(condition) == (condition)으로 해석하면 되나요? ex) UNLIKELY(false)는 그냥(false)로 치환해서 보면 되나요?

그리고

#define DCHECK(condition)      ((void) 0)

이런 문장은 어떻게 해석을 해야 되나요? (void) 0 이 뭘 말하는건가요?

모르는게 너무 많네요. 알려주시면 감사 하겠습니다.

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 어떤 API에서 가져온 코드인지는 모르겠지만, 일단 올리신 코드를 보기좋게 다시 작성해보겠습니다.

    
    #define UNLIKELY(condition) (condition)
    
    #define CHECK(condition) \
        do { \
            if (UNLIKELY(!(condition))) { \
                Fatal(FILE, LINE, "Check failed: %s.", #condition); \
            } \
        } while (0)
    
    #define DCHECK(condition) ((void)0)
    
    

    UNLIKELY()CHECK()에서 사용하므로, 그 이전에 선언돼야 하기 때문에 위로 올렸습니다.

    그리고 매크로 함수에서 #condition 부분의 #이 하는 역할은 뒤에 붙은 값을 그대로 문자열로 치환시키는 것입니다.

    일단 예제를 통해 코드가 어떻게 치환되는 지 보여드리겠습니다.

    int main()
    {
        // 1. bool 값을 직접 입력
        CHECK(false);
    
        // 2. 조건문 입력
        int a = 5;
        int b = 10;
        CHECK(a > b);
    
        return 0;
    }
    
    int main()
    {
        // 1. bool 값을 직접 입력
        do {
            if (!(false)) {
                Fatal(FILE, LINE, "Check failed: %s.", "false");
            }
        } while (0)
    
        // 2. 조건문 입력
        int a = 5;
        int b = 10;
        do {
            if (!(a > b)) {
                Fatal(FILE, LINE, "Check failed: %s.", "a > b");
            }
        } while (0)
    
        return 0;
    }
    

    이제 각 매크로 함수들이 왜 저런 형태로 만들어졌는지 설명드리겠습니다.

    
    // 보통 이렇게 아무 변환도 하지 않는 매크로 함수가 쓰이는 케이스는
    // 크게 2가지 있습니다.
    #define UNLIKELY(condition) (condition)
    
    // 1. 단지 코드 상에서 프로그래머에게 어떤 의미를 전달하고 싶을 때
    //    - 즉, 주석과 비슷한 의미로 쓰는 경우가 있습니다.
    
    // 2. 다른 매크로와 연계하여 사용할 때
    //    - 예를 들어, __WIN32__라는 디파인이 선언되었을 때만 구동되는 코드를 쓰고싶다면
    #ifdef __WIN32__
        #define IF_WIN32_USE(condition) (condition)
    #else
        #define IF_WIN32_USE(condition) ((void)0)
    #endif
    // 이런 식으로 쓸 수도 있는 것이죠.
    // 즉, 동일한 이름의 매크로를 상황별로 다르게 쓰고 싶을 때 입니다.
    
    
    // 다음으로, 아래의 코드는 전형적인 디버깅용 체킹 매크로인데요.
    // condtion에 대입되는 조건문이 결과적으로 false라면, 프로그램을 중지시키고,
    // 로그를 남기는 코드입니다.
    #define CHECK(condition) \
        do { \
            if (UNLIKELY(!(condition))) { \
                Fatal(FILE, LINE, "Check failed: %s.", #condition); \
            } \
        } while (0)
    // #condition은 해당 조건문이 무엇이었는지를 로그에 기록하기 위한 역할입니다.
    // 만약 CHECK(false); 와 같이 조건문이 아닌 false값 자체를 넣는 코드가 있다면,
    // 그건 해당 위치에서 무조건 프로그램을 중지시키겠다는 뜻입니다.(로그를 기록하면서)
    
    
    // 마지막으로 아래 코드는 이미 위에서 한번 예시로 보여드렸는데요.
    // 즉, 해당 코드를 프로그램 상에서 없는 것으로 처리하겠다는 겁니다.
    #define DCHECK(condition) ((void)0)
    
    // 예를 들어, 어떤 함수가 있고, 특정 상황에서만 사용하고 싶으면,
    void SomeFunction() { /*어떤 복잡한 일 수행*/ }
    #ifdef __WIN32__
        #define IF_WIN32_USE(condition) (condition)
    #else
        #define IF_WIN32_USE(condition) ((void)0)
    #endif
    int main()
    {
        IF_WIN32_USE(SomeFunction()); // 이렇게 쓰면, __WIN32__가 선언되었을 때만 함수가 불리겠죠?
    
        // __WIN32__가 선언되지 않았을 때, 아래 코드로 치환되지만, 이 코드는 아무 일도 하지 않는 코드입니다.
        (void)0; // 이런 의미 없는 코드는 컴파일 될 때 자연스럽게 제거됩니다.
    }
    
    • 알기쉽게 설명해 주셔서 감사합니다. 이런코드는 학원에서 배울때도 안 알려 주던데 어떻게 익혀야 될지 모르겠네요 책을 봐야 되는지 ㅎㅎ. 덕분에 많은 도움 됐습니다 다시한번 감사 드립니다. ^^. 알 수 없는 사용자 2016.9.30 13:35
    • 모든 문법과 패턴 등을 순서대로 전부 익히기란 사실 불가능에 가깝습니다. 마치 백과사전을 외우려고 하는 것 처럼 말이죠. 그래서 아무리 잘 가르치는 강사라도 세세한 부분까지 전부 가르쳐주지는 못하지요. 책도 마찬가지 입니다. 결국, 지금처럼 코드를 짜다가 모르는 부분을 발견했을 때, 질문을 통해서 또는 검색을 통해서 차근차근 알아가는 방법이 최선이라고 생각합니다ㅎㅎ Subin Park 2016.9.30 14:20
    • http://stackoverflow.com/questions/109710/likely-unlikely-macros-in-the-linux-kernel-how-do-they-work-whats-their Park June Chul 2016.9.30 17:12
    • 결국 많이 접해보고 경험하는 수밖에 없는거군요. 감사합니다. ^^ 알 수 없는 사용자 2016.9.30 18:58
    • 저 CHECK 코드는 UnitTest++에서 가져오신거 아닌가요? 알 수 없는 사용자 2016.10.1 10:25

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)