티스토리 뷰

C++/General

TCHAR to the rescue!

엘키 2008. 1. 11. 14:01

TCHAR to the rescue!

 

TCHAR 구원의 손길을 내밀다!

 

TCHAR is a character type that lets you use the same codebase for both MBCS and Unicode builds, without putting messy #defines all over your code. A definition of the TCHAR looks like this:

 

TCHAR MBCS 유니코드 빌드 모두의 경우에 같은 기초코드를 사용할 있도록 해주는 문자 타입이다. 여러분의 코드에 너저분한 #define 문들을 넣이 않고도 말이다. TCHAR 정의는 다음과 같다.

 

#ifdef UNICODE

typedef wchar_t TCHAR;

#else

typedef char TCHAR;

#endif

 

So a TCHAR is a char in MBCS builds, and a wchar_t in Unicode builds. There is also a macro _T() to deal with the L prefix needed for Unicode string literals:

 

TCHAR MBCS 빌드시에는 char이고, 유니코드 빌드시에는 wchar_t이다. _T()라는 메소드도 있는데 유니코드 리터럴 문자열에 필요한 L 접두어를 다루어준다.

 

#ifdef UNICODE

#define _T(x) L##x

#else

#define _T(x) x

#endif

 

The ## is a preprocessor operator that pastes the two arguments together. Whenever you have a string literal in your code, use the _T macro on it, and it will have the L prefix added on when you do a Unicode build.

 

## 전처리기 연산자인데 두개의 인수를 함께 붙여준다. 여러분의 코드에 리터럴 문자가 올때마다, _T 매크로를 사용하라, 유니코드 빌드시에 L 문자를 추가해 것이다.

 

TCHAR szNewText[] = _T("we love Bob!");

 

Just as there are macros to hide the SetWindowTextA/W details, there are also macros that you can use in place of the strxxx() and _mbsxxx() string functions. For example, you can use the _tcsrchr macro in place of strrchr() or _mbsrchr() or wcsrchr(). _tcsrchr expands to the right function based on whether you have the _MBCS or UNICODE symbol defined, just like SetWindowText does.

 

SetWindowTextA/W 대한 구분을 숨겨주는 매크로가 있는 것과 마찬가지로, strxxx() _mbsxxx() 문자열 함수 대신에 사용할 있는 메크로도 있다. 예를 들어 strrchr()이나 _mbsrchr() 대신에 _tcsrchr 매크로를 사용할 있다. _tcsrchr _MBCS UNICODE 심볼 어느 것이 정의 되어 있는지에 따라 올바른 함수로 변환된다. SetWindowText() 그러는 것처럼.

 

It's not just the strxxx() functions that have TCHAR macros. There are also, for example, _stprintf (replaces sprintf() and swprintf()) and _tfopen (replaces fopen() and _wfopen()). The full list of macros is in MSDN under the title "Generic-Text Routine Mappings."

 

TCHAR 매크로를 가지는 것은 strxxx() 함수뿐만은 아니다. 예를 들면 (sprintf() swprintf() 대신 사용 가능한) _stprintf (fopen() _wfopen() 대신 사용 가능한) _tfopen 있다. 이런 매크로들의 전체 리스트는 MSDN에서 “Generic-Text Routine Mappings” 제목 아래에 있다.

 

String and TCHAR typedefs

 

문자열과 TCHAR typedef

 

Since the Win32 API documentation lists functions by their common names (for example, "SetWindowText"), all strings are given in terms of TCHARs. (The exception to this is Unicode-only APIs introduced in XP.) Here are the commonly-used typedefs that you will see in MSDN:

 

Win32 API 문서는 일반적인 이름(“SetWindowText” 같은)으로 함수 리스트를 가지고 있다. 모든 문자열은 TCHAR 주어진다. (이것에 대한 예외가 있다면 XP에서 소개되는 유니코드 전용 API들이다.) 여기 MSDN에서 어러분이 찾아볼 있는 일반적으로 사용되는 typedef들이 있다.

 

type

Meaning in MBCS builds

Meaning in Unicode builds

WCHAR

wchar_t

wchar_t

LPSTR

zero-terminated string of char (char*)

zero-terminated string of char (char*)

LPCSTR

constant zero-terminated string of char (const char*)

constant zero-terminated string of char (const char*)

LPWSTR

zero-terminated Unicode string (wchar_t*)

zero-terminated Unicode string (wchar_t*)

LPCWSTR

constant zero-terminated Unicode string (const wchar_t*)

constant zero-terminated Unicode string (const wchar_t*)

TCHAR

char

wchar_t

LPTSTR

zero-terminated string of TCHAR (TCHAR*)

zero-terminated string of TCHAR (TCHAR*)

LPCTSTR

constant zero-terminated string of TCHAR (const TCHAR*)

constant zero-terminated string of TCHAR (const TCHAR*)

 

When to use TCHAR and Unicode

 

TCHAR 유니코드를 사용해야

 

So, after all this, you're probably wondering, "So why would I use Unicode? I've gotten by with plain chars for years." There are three cases where a Unicode build is beneficial:

1.       Your program will run only on Windows NT.

2.       Your program needs to handle filenames longer than MAX_PATH characters.

3.       Your program uses some newer APIs introduced with Windows XP that do not have the separate A/W versions.

 

이제 모든 것을 알게 여러분은 궁금해 할지도 모르겠다. “그렇다면 내가 유니코드를 사용해야 하지? 나는 수년 동안이나 평범하게 char 써왔는데.” 유니코드 빌드가 유용한 세가지 경우가 있다.

 

1.       여러분의 프로그램이 윈도우 NT에서만 실행될 .

2.       여러분의 프로그램이 MAX_PATH 보다 파일명을 다루어야 .

3.       여러분의 프로그램이 별도의 A/W 버전을 가지고 있지 않은 윈도우 XP에서 사용되는 새로운 API들을 사용할 .

 

The vast majority of Unicode APIs are not implemented on Windows 9x, so if you intend your program to be run on 9x, you'll have to stick with the MBCS APIs. (There is a relatively new library from Microsoft called the Microsoft Layer for Unicode that lets you use Unicode on 9x, however I have not tried it myself yet, so I can't comment on how well it works.) However, since NT uses Unicode for everything internally, you will speed up your program by using the Unicode APIs. Every time you pass a string to an MBCS API, the operating system converts the string to Unicode and calls the corresponding Unicode API. If a string is returned, the OS has to convert the string back. While this conversion process is (hopefully) highly optimized to make as little impact as possible, it is still a speed penalty that is avoidable.

 

유니코드 API들의 대부분은 윈도우 9x에서는 구현되지 않았기 때문에, 여러분의 프로그램이 9x에서 실행되길 바란다면, MBCS API 사용해야 것이다. (Microsoft Layer for Unicode라고 불리며 9x에서 유니코드를 사용할 있도록 마이크로소프트에서 내놓은 비교적 최신 라이브러리가 있다.) 하지만, NT 내부적으로 모든 곳에 유니코드를 사용하기 때문에 유니코드 API 사용하면 프로그램의 속도를 올릴 있다. MSCS API 문자열을 넘겨줄 때마다 운영체제는 문자열을 유니코드로 변경하고 해당하는 유니코드 API 호출한다. 문자열이 리턴될 때는 OS 다시 문자열을 변환해야 한다. 이러한 변환 과정은 (다행히) 매우 효율적으로 최적되어 있어서 거의 충격은 없지만, 여전히 피할 없는 속도의 손실이 있는 것은 사실이다.

 

NT allows very long filenames (longer than the normal limit of MAX_PATH characters, which is 260) but only if you use the Unicode APIs. Once nice side benefit of using the Unicode APIs is that your program will automatically handle any language that the user enters. So a user could enter a filename using English, Chinese, and Japanese all together, and you wouldn't need any special code to deal with it; they all appear as Unicode characters to you.

 

NT 아주 파일 이름(MAX_PATH 일반적인 한계치(260)보다 ) 파일 이름을 지원하지만, 유니코드API 사용해야만 한다. 유니코드 API 사용할 경우 얻게 또다른 부수적인 효과는 사용자가 입력한 어떤 언어라도 여러분의 프로그램이 자동적으로 처리할 것이라는 점이다. 사용자는 영어, 중국어, 일본어 모두를 함께 사용하여 파일 이름을 입력할 있고, 여러분이 이를 처리하기 위한 코드를 따로 작성할 필요는 없을 것이다. 모든 문자가 유니코드 문자로 여러분에게 보여질 것이다.

 

Finally, with the end of the Windows 9x line, MS seems to be doing away with the MBCS APIs. For example, the SetWindowTheme() API, which takes two string parameters, only has a Unicode version. Using a Unicode build will simplify string handling as you won't have to convert from MBCS to Unicode and back.

 

마지막으로, 9x 대한 이야기에 덧붙여서, MS MBCS API 사용하지 않으려고 하는 같다. 예를 들면, SetWindowTheme() API 두개의 파라미터를 받는데, 유니코드 버전만을 가지고 있다. 유니코드 빌드를 사용하면 문자열 조작을 간단하게 있고 여러분이 MBCS에서 유니코드로 반대로 변환할 필요는 없게 것이다.

 

And even if you don't go with Unicode builds now, you should definitely always use TCHAR and the associated macros. Not only will that go a long way to making your code DBCS-safe, but if you decide to make a Unicode build in the future, you'll just need to change a preprocessor setting to do it!

 

여러분이 지금 유니코드 빌드를 하지 않는다고 하더라도, 여러분은 항상 TCHAR 관련 매크로를 사용해야 한다. 여러분의 코드가 DBCS 대해서 안전하게 하기 위한 것뿐만이 아니며, 여러분이 장래에 유니코드 빌드를 만드려고 결정할 , 간단히 전처리기 세팅을 바꿔주기만 하면 것이기 때문이다.



[Unicode] 2바이트가 하나의 문자를 나타내며, 세계 각국의 언어를 동일한 코드로 표현할 있습니다. Windows NT/2000 운영체제는 내부적으로 Unicode 사용하고 있습니다. 그렇기 때문에 API 호출시에 Unicode 사용한다면 보다 효율적입니다. C++에서는 wchar_t 타입을 사용합니 .

[MBCS/DBCS]
하나의 문자를 나타내기 위해서 바이트 이상이 사용됩니다. DBCS 바이트 혹은 바이트가 하나의 문자를 나타내는 MBCS 특수한 경우입니다.
C++
에서는 unsigned char 타입을 사용합니다.( 보통은 char 사용하는 같습니다)

[ANSI]
바이트로 하나의 문자를 나타내는 코드입니다. C++ 에서는 char 타입을 사용합니다.

[TCHAR] char
혹은 wchar_t 있는 매크로 입니다.

-------------------------------------------------------------------

Unicode
사용해서 프로그램을 작성하는 것은 다음과 같은 장단점이 있습니다.

장점 - Windows NT/2000에서, 보다 효율적이다.
단점 - Windows 9X 에서 실행되지 않는다.

MBCS/ANSI
사용해서 프로그램을 작성하는 것은 다음과 같은 장단점 있습니다.

장점 - Windows 9X/NT/2000 에서 돌아간다.
단점 - Windows NT/2000 에서, 보다 비효율적이다.

------------------------------------------------------------------

, 상황에 맞는 선택이 필요한 것인데, 그렇다고 상황이 변할때 마다 코드를 재작성 수는 없는 일이기에 TCHAR 라는 매크로를 사용하기에 이르렀습니다.

TCHAR
평소에는 char 활약하다가 유사시에는 wchar_t 되는 매크로입니다.

관련된 내용은 훌륭한 서적/참고 자료가 많이 있으므로 생략하고 간단한 참고 자료를 제시하겠습니다.

-----------------------------------------------------------------

프로젝트에서 UNICODE 혹은 _UNICODE라는 심볼이 미리 정의되는 경우 TCHAR wchar_t 돌변합니다. 물론 이는 아주 단적인 예이고, 올바르게 표현하자면 다음과 같이 것입니다.

UNICODE
미리 정의된 경우 winnt.h에서 다음의 매크로는 화살표에 이끌려 다음과 같이 정의됩니다.

TCHAR --> wchar_t

TEXT,__TEXT --> L

_UNICODE 미리 정의된 경우 tchar.h에서 다음의 매크로는 화살표에 이끌려 다음과 같이 정의됩니다.

TCHAR --> wchar_t

_T,__T,_Text --> L

쉽게 얘기해서 UNICODE SDK에서 쓰는 것이고 _UNICODE CRT에서 사용하는 것입니다.

우리가 알아야 것은 가지 모두 정의해야 한다는 점입니다.

------------------------------------------------------------------

_MBCS
미리 정의된 경우 다음의 매크로는 화살표에 이끌려 다음과 같이 정의됩니다.

TCHAR --> char

_T,__TEXT --> 사라짐

위에서 언급한 무엇도 정의되지 않은 경우 다음의 매크로는 화살표에 이끌려 다음과 같이 정의됩니다.

TCHAR --> char

댓글