헷갈리는 유니코드 출력: %s vs %S

@codemaru · July 19, 2011 · 4 min read

유니코드는 참 사람을 헷갈리게 만듭니다. 유니 코드가 아니라 문자열이란 자체가 사람을 헷갈리게 만드는 것 같아요. 오늘은 그 중에서도 특히나 우리를 더 헷갈리게 만드는 포맷 문자열 변환 지시자 %s와 %S에 대해서 살펴보겠습니다. 우선 %s와 %S가 먼지에 대해서 알아볼까요. 일단 아래 코드를 봅시다.

printf(“%s”, str);

C언어 처음 배우는 학생도 다 알법한 코드죠. str이라는 문자열을 출력하는 코드입니다. 그러면 다음은요?

printf(“%S”, str);

네. 이건 C언어만 배워서는 알긴 힘들지만 어쨌는 앞서 설명한 것과 비슷하게 문자열을 출력하는 역할을 합니다.

그렇다면 대문자 %S와 소문자 %s는 무엇이 다른 걸까요? 바로 변환 방식입니다. 설명하려면 조금 어려운데요. %s는 사용되는 함수와 동일한 문자열 타입으로 출력을 하는 것이고, %S는 사용되는 함수의 반대되는 문자열 타입으로 출력을 하는 지시자입니다. 듣고도 모르겠죠. 당연합니다. ㅋㅋ~ 예를들어 보겠습니다. wprintf에 %s를 사용했다. 그러면 뒤에 str은 wchar_t *로 인식하겠다는 말입니다. %S를 사용했다. 그러면 뒤에 str은 char *로 인식하겠다는 거죠. printf는 어떨까요? %s를 사용하면 char *, %S를 사용하면 wchar_t *로 변환해서 출력합니다. 이해되시나용?

헷갈리지만 자동으로 변환을해서 출력해주니 편리한 기능이긴 합니다. 하지만 사실 대문자 %S 옵션은 사용하지 않는 편이 좋습니다. 왜냐구요? 헷갈리잖아요.

다음 코드를 봅시다.

TCHAR *str;

_tprintf(_T(“%s”), str);

위의 구문은 전형적으로 MBCS빌드와 유니코드 빌드에서 다 안전한 코드입니다. 코드에서 향기가 느껴지지 않으신가요? ㅎㅎ~

wchar_t *str;

_tprintf(_T(“%S”), str);

자 이 코드는 어떻습니까? 먼가 우스꽝 스럽죠. 맞습니다. 이 코드는 유니코드 빌드에서 실패하는 코드입니다.

wchar_t *str;

printf(“%S”, str);

%S 옵션이 유일하게 힘들 얻는 순간입니다. 하지만 이 순간에서 조차도 편리하긴 하지만 헷갈리는건 어쩔 수 없습니다. 왜냐구요? %S만 보고는 이게 어떻게 변환되는 건지 추론을 할 수 없기 때문이죠. printf까지 봤을 때, 아 이게 wchar_t *로 변환되는 거구나라고 판단할 수 있기 때문입니다. 뇌에 부담을 준다고 생각할 수 있겠습니다.

이런 헷갈리는 문제 때문에 다른 변환 지시자들이 존재합니다. 바로 %hs, %ws(=%ls)가 그것이죠. %hs는 대상을 함수에 상관없이 char *로 변환해서 출력해 주는 역할을 합니다. 반대로 %ls, %ws는 wchar_t *로 변환해서 출력하는 역할을 하죠. 따라서 마지막에 쓴 코드는 다음과 같이 사용하는게 덜 헷갈리는 코드라고 할 수 있겠습니다.

wchar_t *str;

printf(“%ws”, str);

 15  0

 

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중