본문 바로가기

C++/C, C++, STL

char, tchar_t 그리고 TCHAR 차이점

문자(char) 타입

char 타입은 C와 C++에서 지원하는 문자를 저장하는 데이터 타입입니다.

하지만 char 타입 변수를 선언하고 97이라는 값을 대입하면 실제로는 a 문자가 표시됩니다.

char c = 97;

// print 'a' character
std::cout << c << std::endl;

이는 char 타입이 ASCII 또는 ISO-8859 UTF-8로 인코딩되는 유니코드 문자 집합을 지원하기 때문입니다.

이번에는 sizeof를 사용해 char 타입의 크기를 확인해봅니다.

char c = 97;

// print 'a' character
std::cout << c << std::endl;
// print 1 bytes
std::cout << sizeof(c) << " bytes" << std::endl;

char 타입은 1바이트를 사용하는 것으로 확인되며, 이는 char 타입이 저장하는 문자 집합의 표현 범위와 일치합니다.

더보기

ASCII 그리고 UTF-8로 인코딩되는 유니코드 문자 집합은 1바이트로 표현됩니다.

만약 char 타입 변수에 한글 문자를 대입하려고 하면 overflow in implicit constant conversion 컴파일 오류가 발생합니다.

한글 문자는 2바이트 이상으로 표현되기 때문입니다.

// warning: overflow in implicit constant conversion
char c = '가';

와이드 문자(wchar_t) 타입

UTF-16으로 인코딩되는 유니코드를 표현하려면 char 타입 대신 wchar_t 타입을 사용합니다.

wchar_t는 한글 문자 등의 유니코드 지원을 위해 2바이트의 저장 공간을 확보하며 문자열의 앞에 L 문자를 추가하여 wchar_t 타입임을 추론하도록 합니다.

std::wprintf(L"가나다라마바사");

윈도우 API에서 인자로 ANSI 코드를 전달할 경우 내부적으로 유니코드로 변환합니다.

따라서 윈도우 환경에서 wchar_t를 사용하면 한글 문자 등의 사용 외에도 성능상 약간의 이점이 있습니다.

호환성을 위한 MS의 TCHAR 타입

초기의 문자열 처리는 ASCII 코드 기반으로 작성되었습니다.

char c[] = "Hello world!";

이후 C++에서 WBCS(Wide Byte Character Set)-2바이트 문자셋 사용을 위해서 기존 char 타입과 wcahr_t 타입의 혼용이 이뤄지게 됩니다.

wchar_t tc[] = L"Hello world!";

프로그램의 ASII 코드 또는 유니코드 사용 여부에 따라서 데이터 타입을 선택하면 되지만, 문자열 리터럴 사용의 경우 처리 코드가 조금 더 복잡해집니다.

만약 프로그램 환경은 ASCII 코드 환경이지만 유니코드 표현이 필요하다면 문자열 리터럴 사용 시 문자 집합을 지정해줘야 합니다.

std::cout << L"Hello world!" << std::endl;

또는 반대의 경우도 마찬가지로, 프로그램 환경과 필요로 하는 문자 집합에 따라서 코드가 이중화되는 문제가 발생합니다.

이런 점을 해결하기 위해서 MS에서 제안한 방법은 전처리 함수를 사용해 프로그램 환경에 따라서 형 변환을 자동화하는 방법입니다.

즉, ASCII 코드 환경에서는 CHAR로 변환하고 유니코드 환경에서는 WCHAR로 변환하여 사용하는 것이며, 이는 컴파일러 설정에 따라서 결정됩니다.

#ifdef UNICODE
    typedef WCHAR TCHAR;
#else
    typedef CHAR TCHAR;
#endif

프로그램 환경에 상관 없이 TCHAR을 사용하면 컴파일러 설정에 따라서 문자열 타입을 결정하게 됩니다.

마찬가지로 문자열 리터럴의 경우도 전처리 함수로 정의됩니다.

#ifdef _UNICODE
    #define __T(x) L ## x
#else
    #define __T(x) x
#endif

#define _T(x)        __T(x)
#define _TEXT(x)     __T(x)

문자열 리터럴의 사용 시에는 다음과 같이 문자열 앞에 _T 문자를 추가합니다.

std::cout << _T("Hello world!") << std::endl;

이렇게 하면 프로그램 환경에 맞춰 ASCII 또는 유니코드가 자동으로 선택됩니다.

더보기

TCHAR와 _T 사용을 위해서는 <tchar.h> 헤더 파일을 선언합니다. 보통은 <Windows.h>를 함께 선언합니다.

#include <Windows.h>
#include <tchar.h>

정리 및 복습

  • 문자 char 타입은 1바이트의 표현 범위를 갖으며 ASCII 코드 또는 UTF-8로 인코딩된 유니코드 표현을 위해 사용합니다.
  • 와이드 문자 wchar_t 타입은 2바이트의 표현 범위를 갖으며 UTF-16으로 인코딩된 유니코드 표현을 위해 사용합니다.
  • wchar_t 타입의 문자열 리터럴을 사용하기 위해서는 문자열 앞에 L 문자를 추가합니다.
  • 프로그램 실행 환경과 상관 없이 문자 집합을 유연하게 표현하기 위해서 MS에서는 TCHAR 타입을 지원합니다.
  • TCHAR 타입의 문자열 리터럴을 사용하기 위해서는 문자열 앞에 _T 문자를 추가합니다.