물마중
[Windows System] 문자셋 (Character Sets) 본문
1. 문자셋(Character Set)의 종류와 특성
SBCS(Single Byte Character Set) : 1바이트로 문자를 표현한다. 대표적으로 아스키 코드(ascii code)가 있다.
MBCS(Multi Byte Character Set) : 문자를 표현 하는데 있어서 아스키 코드는 1바이트로, 그 외에는 2바이트로 처리한다.
WBCS(Wide Byte Character Set) : 모든 문자를 2바이트로 표현한다. 대표적으로 유니코드(UNICODE)가 있으며, 전세계의 모든 문자를 표현할 수 있다.
2. WBCS 기반 프로그래밍
기본적으로 운영체제에서는 문자열을 MBCS 기반으로 처리한다.
예)
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "AB가나";
int len = strlen(str);
printf("%d", len);
return 0;
}
실행 결과
이 코드의 실행 결과에서 MBCS 기반으로 프로그래밍 했을때 생기는 문제점을 알게될 것이다. strlen(string length)함수는
입력한 문자열의 길이를 구하고자 하는 함수이다. 보는 바와 같이 "AB가나" 즉 4개의 문자들이 입력한 것을 알 수 있지만, strlen 함수는 널문자를 제외한 바이트 크기 즉 6바이트를 값으로 출력한다. 이는 프로그래머가 원하는 결과가 절대 아닐 것이다. (문자열마다 할당 바이트가 다르기 때문에 생기는 문제점)
이러한 문제점의 한 해결책이 WBCS 기반 프로그래밍이다.
WBCS 기반으로 프로그래밍 하기 위해선 SBCS 기반의 함수를 WBCS 기반의 함수로 바꿔줘야 한다.
SBCS 함수 | WBCS 함수 |
main | wmain |
char | wchar_t |
"상수" | L"상수" |
strlen | wcslen |
strcpy | wcscpy |
strncpy | wcsncpy |
strcat | wcscat |
strncat | wcsncat |
strcmp | wcscmp |
strncmp | wcsncmp |
printf | wprintf |
scanf | wscanf |
fgets | fgetws |
fputs | fputws |
(참고 : wprintf, fputws 와 같은 함수들을 통해서 유니코드 기반으로 한글을 출력하고 싶다면 함수를 호출하기 전에
_wsetlocale(LC_ALL, L"korean"); // #include <locale.h>
_wsetlocale는 프로그램이 실행되는 나라 및 지역에 대한 정보를 설정하는 함수이다.)
WBCS 함수를 사용할때는 파라미터도 모두 유니코드 기반 문자열이어야 한다.
예)
#include <stdio.h>
int wmain(int argc, wchar_t* argv[])
{
for(int i = 1 ; i < argc; i++)
{
wprintf(L"%s", argv[i]);
}
return 0;
}
3. MBCS, WBCS 동시지원 프로그래밍
일반적인 운영체제는 MBCS를 지원하지만 이도 점점 WBSC로 넘어오고 있다. 하지만 프로그램의 호환성을 위해서 두 문자셋 환경에서 모두 올바르게 동작하기 위한 프로그래밍 습관이 필요하다. 이를 위해서 조건부 컴파일을 사용한다.
1) Windows에서 정의하고 있는 새로운 자료형
소주제에서 새로운 자료형이라고 표현하였지만, 전혀 새로운 자료형이 아니다. 기존에 존재하는 자료형을 조합하여 windows 만의 자료형으로 새롭게 정의한 것에 지나지 않는다. 이는 의미를 더욱 확실하게 하며, 코드 수정 시에 발생하는
많은 시간의 소비와 오류발생률을 줄일 수 있다.
(프로젝트 진행 시에 그 성격에 맞는 자료형을 정의하여 사용하면 많은 장점을 갖는다. 예를 들어 사이즈를 표시하는 자료형을 단순히 int형이나 long형등의 정수 자료형을 쓰는 것보다 새롭게 정의하여 size_t 등으로 사용하는 것이 더욱 효율적이다.)
typedef char CHAR;
typedef wchar_t WCHAR;
#define CONST const;
typedef CHAR* LPSTR;
typedef CONST CHAR* LPCSTR;
typedef WCHAR* LPWSTR;
typedef CONST WCHAR* LPCWSTR;
위에서 언급했던 내용을 다시 정리하겠다.
프로젝트 진행시에 자료형을 정의하여 사용하면 좋은 이유
1. 선언의 편리성 : typedef unsigned int size_t (긴 문장을 간결하게 대체하며 의미도 강하게 부여된다)
2. 확장의 용이성 : typedef unsigned char STR_LEN -> typedef unsigned int STR_LEN
(한번의 수정으로 STR_LEN 자료형을 쓰는 모든 변수가 char->int 로 확장되었다))
2) MBCS와 WBCS를 동시에 지원하기 위한 매크로
Windows에서 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기반의 환경이라면(#indef UNICODE) TCHAR, LPTSTR, LPCTSTR 등을 WCHAR, LPWSTR 등의 유니코드 자료형으로 사용하지만, 그렇지 않다면(#else) MBSC환경의 자료형으로 정의된다.
#ifdef _UNICODE
#define __T(x) L ## x
#else
#define __T(x) x
#endif
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
3) MBCS와 WBCS를 동시에 지원하기 위한 함수
tchar.h 에 선언되어 있는 함수이름 매크로이다.
#ifdef _UNICODE
#define _tmain wmain
#define _tcslen wcslen
#define _tcscat wcscat
#define _tcscpy wcscpy
#define _tcsncpy wcsncpy
#define _tcscmp wcscmp
#define _tcsncmp wcsncmp
#define _tprintf wprintf
#define _tscanf wscanf
#define _fgetts fgetws
#define _fputts fputws
#else
#define _tmain main
#define _tcslen strlen
#define _tcscat strcat
#define _tcscpy strcpy
#define _tcsncpy strncpy
#define _tcscmp strcmp
#define _tcsncmp strncmp
#define _tprintf printf
#define _tscanf scanf
#define _fgetts fgets
#define _fputts fputs
#endif
4) 실제 적용( 위에 1), 2), 3)의 선언들을 잘 참조하면서 하나씩 순서대로 적용해본다)
TCHAR str[5];
#define UNICODE (유니코드가 정의되어 있다면)
TCHAR str[5]; -> WCHAR str[5]; -> wchar_t str[5];
유니코드가 정의되어 있지 않다면
TCHAR str[5]; -> CHAR str[5]; -> char str[5];
_T("BAB5");
_T("BAB5"); --> __T("BAB5");
#define _UNICODE
__T("BAB5"); --> L"BAB5";
유니코드가 정의되어 있지 않다면
__T("BAB5"); --> "BAB5";
_tmain
#define _UNICODE
_tmain --> wmain
유니코드가 정의되어 있지 않다면
_tmain --> main
예)
#define UNICODE // WBCS 지원, 만약 이부분을 주석처리할 경우 MBCS 지원
#define _UNICODE // WBCS 지원, 만약 이부분을 주석처리할 경우 MBCS 지원
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
int _tmain(int argc, TCHAR* argv[])
{
LPTSTR str1 = _T("HACKER");
TCHAR str2[100] = _T("BAB5");
TCHAR str3[20];
LPCTSTR pstr = str1;
_tprintf(_T("str1 len = %d \n"), _tcslen(str1));
_tscanf(_T("%s"), str3);
_tcscat(str2, str3);
_tprintf(_T("%s\n"), str2);
return 0;
}
'Programming > Windows System' 카테고리의 다른 글
[Windows System] 프로세스간 통신(IPC) 기법_메일슬롯(MailSlot) 방식 (0) | 2011.01.22 |
---|---|
[Windows System] 커널 오브젝트(Kernel Objects)_0x01 (0) | 2011.01.22 |
[Windows System] 프로세스 생성함수_CreateProcess() (0) | 2011.01.22 |
[Windows System] 프로세스의 생성과 소멸 (0) | 2011.01.22 |
[Windows System] 64비트 기반 프로그래밍 (0) | 2011.01.22 |