II : 아스키코드 VS 유니코드
뇌를 자극하는 윈도우즈 시스템 프로그래밍 을 읽고 정리한 문서입니다 ;)
Windows에서의 유니코드
아스키코드는 미국에서 정의하고 있는 표준이다. 알파벳 26자에 몇몇 확장 문자를 포함해도 256개를 넘지 않기에, 1바이트로 표현이 되는 문자이다.
하지만 다른 국가의 문자는 그렇지 않기에, 유니코드를 사용하고, 이는 문자를 표현하는데 있어서 균일하게 2바이트를 사용한다.
SBCS 는 Single Byte Character Set으로서, 문자를 표현하는데 1바이트만을 사용하는 방식이다. 아스키코드가 대표적으로 SBCS에 해당된다.
MBCS는 Multi Byte Character Set으로서, 다양한 바이트 수를 사용하여 문자를 표현하는 방식이다. MBCS에서 영어는 1바이트로, 한글은 2바이트로 표현되지만 이 특성 때문에 프로그램 구현이 더욱 까다로워진다.
WBCS는 Wide Byte Character Set으로서, 모든 문자를 2byte로 처리하는 문자셋이고, 흔히 유니코드와 동일시되어 불린다.
char str[] = "ABC한글";
int size = sizeof(str); // 이는 8이다.
int count = strlen(str); // 이는 7이다.
위 예제는 해당 코드 프로젝트가 MBCS 환경에서 동작하고 있음을 알려준다. 이런 때는 1바이트보다 큰 문자들은 문자의 길이를 제대로 가져오지 못하고, 바이트 단위 접근을 할 때 정상 작동을 하지 않는다.
이러한 문제를 해결할 수 있는 방식이 WBCS 방식이다.
WBCS 방식에서는 먼저 자료형 char
대신에 wchar_t
형을 사용해야 한다. wchar_t
형은 2바이트 메모리 공간이 할당된다.
이에 맞추어 문자열의 선언 또한 달라져야 한다. 기존 문자열 선언은 MBCS 방식이기 때문이다.
wchar_t myStr = L"myString내문자열";
문자열 앞에 선언된 문자 L
은 이어서 등장하는 문자열이 유니코드 기반으로 처리되어야 함을 나타낸다. 유니코드에서는 모든 문자가 2바이트이므로, 널 문자 또한 2바이트를 차지한다.
이러한 유니코드 환경에서는 기존에 사용하던 strlen
, strcmp
등의 멀티바이트 문자열을 다루는 함수를 사용할 수 없고, 이와 대응되어 유니코드 방식을 사용하는 wcslen
, wcscmp
등의 함수를 사용해야 한다.
Windows 2000 이상의 운영체제는 내부적으로 모든 문자열을 유니코드 기반으로 처리한다. 또한, 기존 printf
나 fgets
등의 함수 또한 유니코드 전용의 wprintf
나 fgetws
함수로 변경해야 한다.
만일 wprintf
나 fputws
등과 같은 함수를 사용하여 유니코드 기반으로 한글을 출력하고 싶다면, 다음 구문을 실행하여 프로그램이 실행되는 로캘 정보를 설정해주어야 한다.
_wsetlocale(LC_ALL, L"korean"); // #include "locale.h"
또한, 기존의 main(int argc, char* argv[])
함수 또한 유니코드가 호환되는 버전으로 변경해야 한다.
wmain(int argc, wchar_t* argv[]);
MBCS와 WBCS의 동시 지원
아직까지 현존하는 시스템 모두가 완벽히 유니코드 기반으로 동작하지 않기에, 만일 필요하다면 프로그램을 이 둘을 동시에 지원할 수 있게 만들고자 할 수 있다.
#include <windows.h>
를 통해 윈도우 프로그래밍에 필요한 다양한 종류의 헤더파일과 기능을 가져올 수 있게끔 한다면, 윈도우에서 정의하고 있는 자료형을 바로 사용할 수 있다.
typedef char CHAR;
typedef wchar_t WCHAR;
#define CONST const
typedef CHAR * LPSTR;
typedef CONST CHAR * LPCSTR;
typedef WCHAR * LPWSTR;
typedef CONST WCHAR * LPCWSTR;
따라서 윈도우 프로그래밍에서 LPSTR
은 우리가 잘 아는 char *
를 의미함을 알 수 있다.
선언의 용이성과 확장성을 고려해서 typedef
기반으로 적절한 이름의 자료형을 정의하는 것은 아주 효과적인 프로그래밍 습관이다.
또한, 윈도우에서는 MBCS와 WBCS를 동시에 수용하는 형태의 프로그램 구현을 위해서 매크로를 정의하고 있다.
#ifdef UNICODE
typedef WCHAR TCHAR;
typedef LPWSTR LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef CHAR TCHAR;
typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
이렇게 선언하게 되면 만일 UNICODE
가 정의된 환경이라면 WBCS 모드로, 그렇지 않다면 MBCS 모드로 컴파일되게 된다.
또한 문자열을 처리할 때도 _T("ABC가나다");
형태를 취함으로서 모드에 따라 자동으로 래핑될 수 있도록 한다.
문자열을 다루는 함수도 이런식으로 UNICODE
의 정의여부에 따라 올바른 것을 써야 하는데, 이를 해주는 윈도우 헤더가 tchar.h
파일이다.
이것만은 알고 갑시다
- SBCS, MBCS, WBCS의 이해
- SBCS는 문자를 표현하는데 1바이트를, MBCS는 문자를 표현하는데 1바이트 혹은 2바이트를, WBCS는 2바이트를 사용하는 문자셋을 의미한다. 유니코드는 WBCS에 해당한다.
- 유니코드 기반 문자열 처리 함수
- ANSI 표준 문자열 처리 함수는 별도로 유니코드 기반의 버전을 가지고 있다.
UNICODE
와_UNICODE
- 이 두개의 매크로 정의 유무에 따라서 함수의 선언형태가 달라질 수 있도록,
TCHAR
,LPTSTR
등의 자료형을 사용할 줄 알아야 한다.
- 이 두개의 매크로 정의 유무에 따라서 함수의 선언형태가 달라질 수 있도록,
- 유니코드 방식과 MBCS 방식을 모두 지원하기 위한
main
함수의 구성- MBCS 방식을 지원하기 위해서
main
함수가 존재한다면, 유니코드 방식을 지원하기 위해서wmain
함수가 존재하고, 둘을 동시에 지원하기 위해_tmain
함수가 존재한다.
- MBCS 방식을 지원하기 위해서
'공부한 이야기 > 윈도우 OS' 카테고리의 다른 글
IV : 컴퓨터 구조에 대한 두번째 이야기 (0) | 2023.04.29 |
---|---|
III : 64비트 기반 프로그래밍 (0) | 2023.04.29 |
I : 컴퓨터 구조에 대한 첫번째 이야기 (0) | 2023.04.29 |
프로세스 기초 (0) | 2022.08.12 |
운영체제 기초 (0) | 2022.08.12 |