유니코드 (네이버 백과사전)
국제표준으로 제정된 2바이트계의 만국 공통의 국제 문자부호 체계(UCS: Universal Code System)를 말한다. 애플컴퓨터·IBM·마이크로소프트 등이 컨소시엄으로 설립한 유니코드(Unicode)가 1990년에 첫 버전을 발표하였고, ISO/IEC JTC1에서 1995년 9월 국제표준으로 제정하였다. 공식 명칭은ISO/IEC 10646-1(Universal Multiple-Octet Coded Character Set)이다.
유니코드는 전세계 문자코드를 정의하기 위해서 만든 놈이다
그럼 이전에는 어떻게 표현 했는가?
이전에는 알파벳틱한 애들은 1바이트에서 7비트 내로 표현하고(Ascii) 그외에 확장적인 문자가 코드 127 위로 표시되고, 한글과 같이 더 많은 바이트가 필요한 것들은 2바이트로 표현을 했다.
그래서 문제는 코드 127 위로 넘어가면 윈도우의 경우 각 나라의 OS별로 표현하는 방법이 틀렸다
(이전에 터보C 3.0 이전 IDE를 생각하면 될것이다. 콘솔화면으로 표현한 UI에서 옆에 테두리가 어떻게 나왔는지를...)
한글의 경우도 2바이트 문자로 표현을 하였고 이것을 MBCS(Multibyte Character Set) 이라고 한다.
UNICODE
2바이트 문자를 표현하기 위해 만든 C++의 타입이 있었으니 그것이 바로 wchar_t 타입이다.
(그런데 wchar_t 의 경우 OS마다, 컴파일러마다 정의가 약간 틀린듯하다. -_-;; )
그럼 문자열을 어떻게 표현을 할까?
정수를 long 타입으로 표현할때 쓰는 뒤에 L를 붙이는것과 일맥상통 하게 앞에 L 을 붙여서 표현한다.
10 (int)
10L (long)
"a" (char)
L"a" (wchar_t)
wchar_t wsz[] = L"김"; // UNICODE 총 2바이트 사용 (2바이트 문자셋 1개 사용)
char sz[] = "김"; // MBCS 총 2바이트 사용 (1바이트 문자셋 2개 사용)
그리고 wchar_t 타입에 대응되는 표준 라이브러리들이 아래와 같은 놈들이다.
C++ 클래스 : wostream, wfstream, wstring ...
C 함수 : wcslen, wcslen ...
그리고 WinAPI 로는...
MessageBoxW, GetCurrentDirectoryW, CreateDirectoryW
어라.. 근데 처음 보는 놈들일것이다.
MessageBox 는 알아도 MessageBoxW 는 무엇인가...
MSDN 를 뒤져도 찾기가 쉽지 않다.
WinAPI 에서는 문자열을 사용하는 API에 대해서 MBCS와 UNICODE에 대응되는 함수를 각각 가지고 있다.
그리고 거의 모든 API 에서 뒤에는 A(MBCS) 또는 W(UNICODE) 를 붙이는 것으로 표시를 하고 있는것이다.
그래서 MessageBox 라는 것은 함수 이름이 아니며 그것들을 스위칭 하는 매크로 이름이다.
실제 함수는 아래와 같이 MessageBoxA 혹은 MessageBoxW 로 매크로에 의해 치환되는것이다.
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
관련해서 타입들도 이런한 것들이 존재한다.
LPCSTR => const char *
LPCWSTR => const wchar_t *
LPCTSTR => LPCSTR <-> LPCWSTR 스위칭
"김" => const char *
L"김" => const wchar_t *
_T("김") => "김" <-> L"김" 스위칭
이 스위칭들은 UNICODE 와 _UNICODE 매크로 정의에 의해서 각각 해당 함수 혹은 타입으로 정의가 된다.
(UNICODE 와 _UNICODE 을 두개를 같이 정의 해야되는데 왜 2개를 만들었는지 모르겠다. 암튼..)
그리고 MSDN에서는 아래와 같이 함수인양 사기(?)를 치는것이다.
MessageBox
The MessageBox function creates, displays, and operates a message box. The message box contains an application-defined message and title, plus any combination of predefined icons and push buttons.
int MessageBox(
HWND hWnd, // handle of owner window
LPCTSTR lpText, // address of text in message box
LPCTSTR lpCaption, // address of title of message box
UINT uType // style of message box
);
UTF-8, UTF-16 ??
위에서 얘기했듯이 일반적으로 유니코드는 2바이트 문자로 표현을 한다.
그러다 보니 한글 파일의 경우 MBCS나 UNICODE나 크기가 별반 차이가 없다.
그런데 영어권 애들의 파일을 보자..
게네들은 겉으로는 아무것도 낳아진것이 없는데 파일의 크기가 2배가 되어야 한다.
이런 어처구니 없는 경우가 있나..
(내가 생각해도 그렇다. 허나 뒤에가면 우리가 어처구니 없어진다. ㅎㅎ)
그래서 얘네들이 머리를 굴려서 유니코드를 표현하는 방식을 여려게 만들었다.
그것이 바로 UTF (Unicode Transformation Format) 이다.
그중에 일반적으로 유니코드라로 불리는 2바이트 체계 표현이 UTF-16 이고,
영어권은 1바이트 기타 언어는 4바이트까지 가변적으로 표현 가능한것이 UTF-8 이다.
(유니코드의 127 까지의 문자는 ASCII 문자코드와 동일하다. 그래서 영어권 1바이트가 ASCII와 호환이 되는것이다.)
http://ko.wikipedia.org/wiki/UTF-16
http://ko.wikipedia.org/wiki/UTF-8
이러다 보니 한글은 UTF-8 로 가면 4바이트로 표현이 되어 버린다.
UTF-8
그럼 UTF-8 은 어떤 타입을 써야 하는가?
char [] 아니면 wchar_t [] ??
아직까지 표준으로 정해진것은 없는 것으로 안다.
차기 표준에서 이것에 대해서 논의가 되고 있으니 좋은 결과가 있을것으로...
Byte Order Mark
2바이트 혹은 그 이상의 바이트로 표현을 하다보니 정수표현과 같이 머신, 플랫폼 간의 바이트 오더링(little-endian, big-endian)의 문제가 있다.
유니코드 파일
윈도우 유니코드 파일의 경우 아래와 같은 문자를 파일 맨앞에 세팅함으로서 구분을 한다
(이게 표준인지 윈도우만 그런지는 잘 모르겠다...)
유니코드(UTF-16, little-endian) : 0xFF 0xFE
유니코드 big endian (UTF-16, big-endian) : 0xFE 0xFF
UTF-8 : 0xFE 0xFF