c++ 질문 드립니다.

조회수 1676회

안녕하세요. 공부를 하다보니 또 잘 모르는게 나와서; 재차 질문 드립니다.

(질문을 할때 추가 질문 사항이 있으면, 이전글에 update 시키는 것이 맞는건가요? 아님 새글을 써도 되는건가요? 이런 포럼 게시판은 이용이 처음이라 어느게 맞는지 모르겠네요. 알려 주시면 감사하겠습니다.)

질문은 ICU 쪽 코드를 보고 있는데, 좀 이해가 안 가서 코드 첨부하여 질문 합니다.

#define U_ICU_VERSION_SUFFIX _56

#define U_DEF_ICU_ENTRY_POINT_RENAME(x,y) x ## y
#define U_DEF2_ICU_ENTRY_POINT_RENAME(x,y) U_DEF_ICU_ENTRY_POINT_RENAME(x,y)
#define U_ICU_ENTRY_POINT_RENAME(x)    U_DEF2_ICU_ENTRY_POINT_RENAME(x,U_ICU_VERSION_SUFFIX)

UErrorCode err = U_ZERO_ERROR;
U_ICU_ENTRY_POINT_RENAME(reinterpret_cast<void*>(g_icu_data_ptr), &err);

위의 err은 ICU에서 모든 c++ 컴파일러의 에러코드 통일을 위해 정의 된 에러코드 입니다. 정의는 typedef enum UErrorCode{에러코드들...} 으로 정의 되어있고. 위의 U_ZERO_ERROR는 0으로 에러가 없다는 표시 입니다.

g_icu_data_ptr에는 파일경로가 들어갑니다. (ex: d:\test\icu\icudtl.dat 이런식으로)

결과적으로 보면 (reinterpret_cast(g_icu_data_ptr), &err) ## _56 인데 ##이 x와 y를 붙여라 라고 하는 거잖아요? x가 매개변수가 두개인데 _56과 어떻게 붙이라는건지 모르겠네요.

아니면 ##의 사용법이 두 매개변수를 붙이는거 외에 다른 기능이 있는건가요?

알려 주시면 감사하겠습니다 (__)

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

1 답변

  • 제가 ICU쪽 레퍼런스를 잘 몰라서 제대로 답변드리긴 어렵지만,

    일단 올리신 코드에 한에서 C++ 문법적으로만 보고 답변드리겠습니다.

    // 이렇게만 놓고 보면, _56이 정확히 무엇인지 알 수 없습니다.
    // 문맥적으로 보았을 때, 버전 정보를 의미하는 것은 알 수는 있지만,
    // 이것이 단순한 공백 디파인인지, 어떠한 대상을 가리키는 디파인인지는 알 수 없네요.
    #define U_ICU_VERSION_SUFFIX _56
    
    // 아래 코드는 명백하게 x와 y를 코드 상에서 이어붙인다는 의미입니다.
    #define U_DEF_ICU_ENTRY_POINT_RENAME(x,y) x ## y
    
    // 아래 코드는 일단 아무 추가작업 없이 위 코드로 변환되기는 하지만,
    // 이런 코드가 있다는 것은, #ifdef 등을 통해 같은 이름의 다른 정의를 가진 #define이 존재할 확률이 높습니다.
    // 여러 환경(윈도우/맥, 또는 유니코드/ANSI)에 복합적인 대응을 갖출 때 많이 사용합니다.
    #define U_DEF2_ICU_ENTRY_POINT_RENAME(x,y) U_DEF_ICU_ENTRY_POINT_RENAME(x,y)
    
    // 아래 코드는 인자를 하나 받아서 추가적으로 특정 상수값을 포함하여 다른 매크로 함수를 호출하는 용도인 듯 합니다.
    #define U_ICU_ENTRY_POINT_RENAME(x)    U_DEF2_ICU_ENTRY_POINT_RENAME(x,U_ICU_VERSION_SUFFIX)
    
    // 이 코드는 논외로 하겠습니다.
    UErrorCode err = U_ZERO_ERROR;
    
    // 사실상 위의 코드들만이 존재한다면, 아래의 코드는 잘못된 코드입니다.
    // #define을 통한 매크로 함수는 선언부에서 매개변수를 하나로 명시했으면,
    // 호출부에서도 당연히 인자를 하나만 넘기는 게 맞습니다.
    // 제 생각엔, 동일한 이름의 매크로 함수 선언이 추가적으로 있을 듯 합니다.
    // 해당되는 선언을 찾아보셔야 할 듯 합니다.
    U_ICU_ENTRY_POINT_RENAME(reinterpret_cast<void*>(g_icu_data_ptr), &err);
    
    • 말씀 하신대로 ICU가 여러 환경에서 쓰이기 때문에 윈도우에서는 어떻게 mac에서는 어떻게 하라는등 환경에 맞춰 코딩이 되어있구요. 제가 풀어서 적다보니 제일 아래줄 부분을 저렇게 적었는데 실제로는 제일 아랫줄 부분이 udata_setCommonData(reinterpret_cast< void* >(g_icu_data_ptr), &err); 이렇게 되어있고, udata_setCommonData 정의 를 찾아 들어가 보면 #define udata_setCommonData U_ICU_ENTRY_POINT_RENAME(udata_setCommonData) 이렇게 되어있는데 매개변수인 udata_setCommonData의 정의를 찾아 들어가면, U_STABLE void U_EXPORT2 udata_setCommonData(const void *data, UErrorCode *err); 이렇게 되어있습니다. @_@ U_STABLE은 #define U_STABLE U_CAPI 이고, U_CAPI 는 #define U_CAPI U_CFUNC U_EXPORT, U_CFUNC 는 #define U_CFUNC extern "C", 이렇게 정의 되어 있습니다. U_EXPORT는 단순히 #define U_EXPORT 이렇게만 되어있구요. U_EXPORT2 는# define U_EXPORT2 __cdecl 라고 정의 되어있습니다. 결과적으로는 U_ICU_ENTRY_POINT_RENAME(reinterpret_cast(g_icu_data_ptr), &err); 이렇게 되는게 아닌가요? @_@;; 댓글로 쓰니 코드 보기가 불편하네요; 알 수 없는 사용자 2016.10.6 09:54
    • 제가 잘못 본거 같네요.. udata_setCommonData에대한 함수 정의가 따로 되어 있었네요.. 이쪽을 분석 해봐야 될거 같습니다 감사합니다. 알 수 없는 사용자 2016.10.6 10:16

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

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

(ಠ_ಠ)
(ಠ‿ಠ)