2012년 8월 23일 목요일

윈도우즈 시스템 프로그래밍 [2] - 아스키코드 VS 유니코드




윈도우즈 시스템 프로그래밍을 공부하면서 정리한 글입니다.



2장. 아스키코드 VS 유니코드



I. Windows에서의 유니코드 (UNICODE)



1. 문자셋의 종류와 특성


① ASCII Code

- 알파벳 26개 + 확장문자 (그림 문자, 수학기호 ...)
- 256(2의 8승)를 넘지 않아 1바이트(8비트)로 표현 가능

② UNICODE ( = UCS = Universal Character Set)

- 아스키코드 + 지역적 문자셋 코드 + 그외 기타 코드
- 2바이트로 구성

- 문자 셋 : 문자들의 집합 ( = 약속된 문자의 표현 방법)

① SBCS ( Single Byte Character Set )

- 1바이트만을 사용해 문자를 표현하는 방식
- 아스키 코드가 대표적

② MBCS ( Multi Byte Character Set )

- 1바이트와 2바이트를 모두 사용해 문자를 표현하는 방식
- SBCS를 포함 -> 영어는 1바이트, 한글은 2바이트로 표현

 WBCS ( Wide Byte Character Set)

- 모든 문자를 2바이트로 처리하는 문자셋
- 유니코드가 대표적

2. MBCS 기반의 문자열


ex)

char set[] = "ABC한글";

printf("sizeof : %d\n", sizeof(set));
// 8 출력 = ABC(3바이트) + 한글(4바이트) + NULL(1바이트)

printf("strlen : %d\n", strlen(set)); 
// 7 출력 = ABC(길이 3) + 한글(길이 4)   <- 오류!


2. WBCS 기반 프로그래밍


① char 대신 wchar_t를 사용

- char은 1바이트 공간이 할당되지만 wchar_t는 2바이트가 할당 됨. 

② "ABC"를 대신하는 L"ABC"
- 선언 방법 : wchar_t = L"ABC";
- "L" : 이어서 등장하는 문자는 유니코드(WBCS)기반으로 표현한다는 의미
- 유니코드에서는 NULL 문자도 2바이트로 처리됨

③ strlen을 대신하는 wcslen

- strlen -> wcslen
- strcpy -> wcscpy
- strncpy -> wcsncpy
- strcat -> wcsncat
- strcmp -> wcscmp
- strncmp -> wcsncmp

* sizeof는 함수가 아닌 연산자 -> 배열의 크기를 MBCS든 WBCS든 정확히 계산하여 반환

- SBCS 문자열 -> WBCS 기반의 함수에서 사용 불가능 ( 컴파일 에러 )
- WBCS 문자열 -> SBCS 기반의 함수에서 사용 가능

- printf -> wprintf
- scanf -> wscanf
- fgets -> fgetws
- fputs -> fputws

- printf("Hello");       =>        wprintf( L"Hello" );

④ wmain

======== SBCS 기반 ========

int main(int argc, char* argv[]) {

   for ( int i=0; i<argc; i++)
      fupts ( argv[i], stdout);

  return 0;
}

======== WBCS 기반 ========


int wmain(int argc, wchar_t* argv[]) {

   for ( int i=0; i<argc; i++)
      fuptws ( argv[i], stdout);

  return 0;
}

- main 함수는 전달되는 문자열을 MBCS 기반으로 구성함
   => ∴ wmain을 사용해야 함

C:\> test.exe AAA BBB      ------>       "AAA"  "BBB"      ------>    main

C:\> test.exe AAA BBB      ------>       L"AAA"  L"BBB"      ------>    wmain





II. MBCS와 WBCS의 동시 지원



1. #include <windows.h>


- 윈도우즈 기반 플그래밍에서 기본적으로 항상 포함하는 헤더파일
- 자료형 CHAR, WCHAR 등을 가짐
- 윈도우즈 시스템 프로그래밍에 필요한 대부분의 것들을 직/간접적으로 포함


2. Windows에서 정의하고 있는 자료형


- typedef 키워드로 기본자료형에 Windows 스타일의 이름으로 정의함

ex)
 typedef char CHAR;
 typedef wchar_t WCHAR;

 #define CONST const
 typedef CHAR* LPSTR;
 typedef CONST CHAR* LPCSTR;
 typedef WCHAR* LPWSTR;
 typedef CONST WCHAR* LPCWSTR;
 typedef CONST CHAR* LPCSTR;

- Windows 스타일의 이름으로 자료형을  정의하는 이유

① 선언의 편리성
② 확장의 용이성



3. MBCS와 WBCS(유니코드)를 동시에 지원하기 위한 매크로


- Windows에서 동시 지원을 매크로를 통해 지원해줌

ex) tchar.h에 선언된 내용을 정리한 것

#ifdef UNICODE
 typedef WCHAR TCHAR;
 typedef LPWSTR LPTSTR;
 typedef LPCWSTR LPCTSTR;
#else
 typedef CHAR TCHAR;
 typedef LPSTR LPTSTR;
 typedef LPCSTR LPCTSTR;
#endif

- 동시 구현을 위해선 windows.h 뿐만 아니라 tchar.h도 포함해야함

ex)

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

#else
 #define __T(x) x

#endif

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

ex) TCHAR arr[10]

UNICODE 정의 되어 있을 때 :

TCHAR arr[10] --> WCHAR arr[10] --> wchar_t arr[10]

UNICODE 정의 되어 있지 않을 때:

TCHAR arr[10] --> CHAR arr[10] --> char arr[10]

ex) _T("TEXT");

_UNICODE 정의 되어 있을 때 :

_T("TEXT") -->  __T("TEXT");  --> L("TEXT");

_UNICODE 정의 되어 있지 않을 때:

_T("TEXT") -->  __T("TEXT");  --> "TEXT"

ex)

#define UNICODE   // visual studio에는 기본적으로 정의되어 있음
#define _UNICODE   // 해제를 원하면 #undef 사

#include <stdio.h>
#include <tchar.h>
#include <windows.h>

int wmain(void) {

TCHAR str[]=_T("12345");


4. MBCS와 WBCS(유니코드)를 동시에 지원하기 위한 함수들


ex) tchar.h에 정의 되어 있는 내용을 정리

#ifdef _UNICODE

#define _tmain wmain
#define _tcslen wcslen
#define _tcscat wcscat
#define _tprintf wprintf

#else

#define _tmain main
#define _tcslen strlen

#endif

- visual studio에서 프로젝트 생성시 stdio.h, tchar.h와 같이 자주 사용하는 헤더 파일을
 pre-compiled 헤더 형태로 정의해 둠

=> 컴파일 속도 향상을 위해



참고 : 뇌를 자극하는 윈도우즈 시스템 프로그래밍. 윤성우 저



댓글 없음:

댓글 쓰기