반응형

 

 

결론

 

멀티 바이트 혹은 유니코드 모두에서 동작하도록 문자열을 다룰 때는 _TCHAR 형과 _T()를 사용한다.

 

멀티 바이트인지 유니코드인지 환경에 따라 자동으로 변수 이름이나 함수 이름이 변환되겠끔 하기 위해 ‘_t’가 붙은 것을 사용한다.

 

한가지 팁으로는 유니코드로 한글을 출력하기 위해서는 setlocale() 함수를 사용해야 한다.


Wide Character(wchar_t형)

 

1byte가 아닌 그 이상의 byte를 차지하는 정수에 저장되는 문자 코드를 의미한다.

 

흔히 Wide Character로 표현되는 문자 코드는 UNICODE이다.

 

UNICODE를 Wide Character로 표현하는 방법은 UCS-2(2byte), UCS-4(4byte), UTF-16(2byte), UTF-32(4byte) 등이 있다.

 

C표준은 Wide Character를 표현하기 위해 wchar_t 데이터 형을 정의하고 있는데, wchar_t의 정확한 크기는 구현에 따라 다르며 MSVC에서는 내부적으로 unsigned short형(UCS-2)이고, gcc는 int형(UCS-4, UTF-8)을 사용한다.

 

C표준은 wchar_t형의 형식을 통일하는데 실패했으며, 이는 곧 다양한 표현 방법을 선택할 수 있게 되었다는 것을 의미하기도 하는데

즉, wchar_t는 시스템에 따라서 UCS-2 일수도 있고, UTF16일수도 UTF-32일 수도 있다는 것이다.

(gcc에 -fshort-wchar 옵션을 주면 wchar_t가 unsigned short를 사용하도록 설정할 수 있지만, 이렇게 컴파일러 옵션으로 변경했을 경우에 다른 표준 C 라이브러리들이 이 설정에 맞게 동작할지 알 수 없기 때문에 옵션을 설정 안하는 것이 좋다.)

 

C 표준은 wchar_t형 외에도 wint_t를 같이 정의하고 있는데 fgetc()와 같은 함수들을 위함이다.

 

wint_t형은 한 개의 유니코드 값을 주고 받기 위해서 함수 인수나 리턴 값으로 사용되며, wint_t의 배열로서 문자열을 나타내지는 않는다.

( 만약 wide character 버전의 fgetc()가 있다면, wchar_t를 리턴하기 보다는 wchar_t 외의 에러 값도 표현할 수 있는 타입을 리턴해야 하는데, 이때 사용하는 것이 wint_t이다.

그냥 int를 써도 무방할 수 있지만 int가 wchar_t와 똑같이 16비트일 경우가 있을 수 있으므로 wint_t를 사용해야 한다. )

 

MS 윈도우즈에서는 C 표준 말고도 자체 API 상에서 UNICODE를 지원하는데, 이 때는 WCHAR를 사용한다.

(WCHAR는 unsigned short로 MS의 컴파일러에서의 wchar_t형과 일치한다.)

 

C/C++ 소스 파일은 wide character를 받아들이지 않고, ASCII 파일만을 인식한다.

(ASCII와 호환되는 MBCS나 UTF-8만 가능하다)

 

대신 C 표준은 wchar_t를 위해 문자열 상수의 변환을 지원하도록 했다.

(즉, 후에 나올 내용 중에 유니코드 환경일 때 문자열 처리 part에서 나올 wide string literal 표현법인 문자열 상수 앞에 L을 붙이는 것이다.)

 

다만, Wide string literal 방법을 사용했을 때 해석은 MSVC와 GCC가 다르다.

 

MSVC는 소스 파이 안에 있는 문자열을 시스템의 기본 locale에 따라 인식한 후에 UCS-2로 변환한다.

즉, 컴파일 시점의 사용자 설정을 기준으로 변환한다는 것이다.

(프로그램 출력물 안에는 원하는 대로 UCS-2 문자열로 저장이 된다.)

MSVC의 소스파일에서는 

 

gcc 3.4 이전 버전은 Wide string literal을 제대로 지원하지 못한다.

변환 없이 그저 각 byte를 4byte로 복사해 넣는 방식으로 동작한다.

 

gcc 3.4 이후 버전은 기본적으로 UTF-8로 인식하고 이를 UTF-32로 변환해서 저장한다.

그리고 입력 문자열을 지정할 수 있는 옵션이 추가되었다.

 


문자 코드

 

ASCII 코드

영어, 부호, 숫자 등을 128개의 수로 나타내는 방법, 단점은 영어 이외에 한글이나 다른 언어들은 표현할 수 없다.

 

멀티 바이트(MBCS = Multi Byte Character Set)

영어는 1byte, 이 외 문자는 2byte로 처리, 하지만 이는 세계 표준이 아닌 MS에서만 사용하는 것이다.

 

유니코드(WBCS = Wide Byte Character Set)

모든 문자를 2byte로 처리(GCC는 4byte로 처리)

 


멀티 바이트와 유니코드 환경에 따른 변수와 함수 이름

 

데이터 타입을 _TCHAR로 쓰면 유니코드 환경일 때 wchar_t 형으로 재정의한다.

 

Visual Studio에서 유니코드를 사용하기 위해서는 wchar, wprintf와 같은 ‘w’ 문자가 붙은 변수 이름이나 함수 이름으로 사용해야 한다.

 

하지만 매번 멀티 바이트 환경에서 유니코드 환경으로 변경 후 개발할 때 혹은 그 반대의 경우에 변수 이름과 함수 이름을 바꾸는 작업을 하기에는 너무 번거로움으로 환경이 어떤지 검사하여 알아서 변환해주는 _tprintf() 같은 함수를 사용한다.

 

TCHAR형 함수들

 

header file string.h mbstring.h string.h or wchar.h tchar.h
header file description _UNICODE 또는 _MBCS가 정의되어 있지 않다. _MBCS가 정의되어 있다. _UNICODE가 정의되어 있다. _UNICODE 또는 _MBCS가 정의되어 있다.
문자열 복사  strcpy _mbscpy wcscpy _tcscpy
문자열을 사이즈만큼 복사 strncpy _mbsncpy wcsncpy _tcsncpy
문자열 길이 확인
strlen
_mbslen wcslen _tcslen
두 문자열을 이어주는 strcat _mbscat wcscat _tcscat
두 문자열을 사이즈만큼 이어주는 strncat _mbsncat wcsncat _tcsncat
문자열 비교 strcmp _mbscmp wcscmp _tcscmp
두 문자열을 사이즈만큼 비교 strncmp _mbsncmp wcsncmp _tcsncmp
대소문자를 구별하지 않고 문자열을 비교 stricmp _mbsicmp wcsicmp _tcsicmp
사이즈만큼 대소문자를 구별하지 않고 문자열을 비교 strnicmp _mbsnicmp wcsnicmp _tcsnicmp
문자 찾기 strchr _mbschr wcschr _tcschr
문자 찾기(문자열 끝에서부터 검색) strrchr _mbsrchr wcsrchr _tcsrchr
문자열 찾기 strstr _mbsstr wcsstr _tcsstr
문자 찾기(두번째 인수를 찾고자 하는 문자들의 집합(문자열)으로 구성한다.) strpbrk _mbspbrk wcspbrk _tcspbrk
문자열 자르기(두 번째 인수를 집합(문자열)으로 구성 가능하다.) strtok _mbstok wcstok _tcstok
문자 치환(첫번째 인수의 모든 문자를 두 번째 인수 문자로 변경한다.) strset _mbsset wcsset _tcsset
사이즈 만큼 문자 치환 strnset _mbsnset wcsnset _tcscnset
대문자로 치환 strupr _mbsupr wcsupr _tcsupr
소문자로 치환 strlwr _mbslwr wcslwr _tcslwr
문자열 역정렬 strrev _mbsrev wcsrev _tcsrev

 


멀티 바이트와 유니코드 환경에 따라 문자열 처리 할 때

 

멀티 바이트로 할 때는 “ “이렇게 더블 쿼터로 문자열을 감싸고,

유니코드로 할 때는 L” “ 이렇게 더클 쿼터로 문자열을 감싸고 앞에 L을 붙여줬다.

멀티바이트 일 때 : MessageBox(NULL, "hello", "hello", MB_OK);
유니코드 일 때 : MessageBox(NULL, L"hello", L"hello", MB_OK);

 

하지만 만약 유니코드 환경에서 코드를 작성한 후 멀티바이트로 환경을 변경해서(외부 라이브러리와의 호환성 등의 이유로) 코드를 작성할 때는 L”hello”에서 “hello”로 하나하나 바꿔줘야 했다.

 

그래서 나온 솔루션이 TEXT(””)와 _T(””)을 #define 하는 것이다.

 

TEXT(””)는 WinNT.h 파일에서 정의 했지만, TEXT 라는 함수 이름도 길어서 tchar.h에서 _T로 이름을 정의 한 것이다.

 

Win32에서는 TEXT(””)을 쓰고, MFC에서는 _T(””)을 사용한다고 하는데, win32와 MFC에 상관없이 _T(””)을 사용하고 싶을 때는 tchar.h 헤더파일을 포함하면 된다.

 

MessageBox(NULL, TEXT("hello"), TEXT("hello"), MB_OK);
#include tchar.h

MessageBox(NULL, _T("hello"), _T("hello"), MB_OK);

 

위와 같이 입력하면 알아서 멀티바이트일 때와 유니코드일 때에 따라 코드를 변환한다.

 

// 멀티바이트 일 때
MessageBox(NULL, "hello", "hello", MB_OK);
// 유니코드 일 때
MessageBox(NULL, L"hello", L"hello", MB_OK);

 


결론

 

멀티 바이트 혹은 유니코드 모두에서 동작하도록 문자열을 다룰 때는 _TCHAR 형과 _T()를 사용한다.

 

멀티 바이트인지 유니코드인지 환경에 따라 자동으로 변수 이름이나 함수 이름이 변환되겠끔 하기 위해 ‘_t’가 붙은 것을 사용한다.

 

한가지 팁으로는 유니코드로 한글을 출력하기 위해서는 setlocale() 함수를 사용해야 한다.

 


 

"", L"", TEXT(""), _T("") 차이점 : http://x108zero.blogspot.com/2013/12/text-t-l.html

TCHAR, wchar, char란 무엇인가?? : https://redcoder.tistory.com/137

 

문자열 관련 함수들 : https://mrhook.co.kr/202

 

와이드 문자란 : https://blog.daum.net/rayolla/376

 

TCHAR형이란 https://hwan-shell.tistory.com/134

반응형

+ Recent posts