[스터디] 시스템 프로그래밍 - Chapter 2. 아스키코드 vs 유니코드

2023. 9. 11. 22:13·독서/뇌를 자극하는 윈도우즈 시스템 프로그래밍

뇌를 자극하는 윈도우즈 시스템 프로그래밍(저자, 윤성우)


01. Windows에서의 유니코드(Unicode)

- 문자셋Character Sets의 종류와 특성

가장 대표적인 문자셋에 해당하는 아스키코드ASCII CODE와 유니코드UNICODE에 대해서 살펴보자. 아스키코드는 미국에서 정의한 표준이며 알파벳의 개수는 26개다. 확장 문자를 포함해도 256개를 넘지 않는다. 그렇기 때문에 1바이트로 충분히 표현 가능하다.

 

하지만 다른 언어를 사용하는 문화권에서는 아스키코드를 사용하기에 적절하지 않다. 이때, 모든 문자를 균일하게 2바이트를 사용해서 나타내는 유니코드가 나타났다. 2바이트로는 65,536개(256 * 256)의 문자를 나타낼 수 있다.

문자셋 vs 인코딩 : 문자셋은 문자 집합을 의미하고, 인코딩은 문자셋을 Byte와 맵핑하는 과정 및 규칙을 의미한다.

 

문자셋은 문자 집합을 의미한다. 즉, 약속된 문자의 표현 방법을 의미하고 종류에 따라서 크게 3가지로 구분할 수 있다.

종류 설명
SBCS
(Single Byte Character Set)
문자를 표현할 때, 1 Byte만 사용하여 표현한다. 아스키코드가 이에 해당한다.
MBCS
(Multi Byte Character Set)
동일한 Byte로 접근하는 것이 아니라, 다양한 Byte 수를 통해서 수를 표현한다.

( 참고로 유니코드는 MBCS에 포함되지 않는다. MBCS는 SBCS의 방식을 포함하고 있다. 그렇기 때문에 특수한 경우 1 Byte로 문자를 표현하고 있기 때문이다. )
WBCS
(Wide Byte Character Set)
모든 문자를 2 Byte로 표현하는 문자셋이다. 유니코드가 해당하는 문자셋이다.

 

- MBCS 기반의 문자열

* 해당 코드가 도출하는 결과값은 작업하는 환경 및 세팅에 따라서 변동될 수 있음을 알림.

#include <stdio.h>
#include <string.h>

int main(void)
{
	char str[] = "ABC한글";
	int size = sizeof(str);
	int len = strlen(str);

	printf("Array Size : %d \n", size);
	printf("Character Length : %d \n", len);

	return 0;
}

▶ 실행 결과

Array Size : 8
Character Length : 7

 

위 코드를 통해 나타난 결과는 배열 크기를 8, 문자열 길이를 7로 나타냈다. 왜 이러한 결과가 나타났는지 보자.

 

Array Size : 8  → ABC ( 3 Byte ), 한글 ( 6 Byte ), \n ( 1 Byte )

Character Length : 7 → ABC ( 3 Byte ), 한글 ( 6 Byte )

 

문자열의 종류를 설명할 때, MBCS는 특수한 경우에는 1 Byte를 사용한다고 설명한 적이 있다. 이번 예제에서는 영문에는 1 Byte이고, 한글에서는 2 Byte가 사용된 것을 통해서 MBCS로 실행되었음을 알 수 있다.

 

Character Length는 strlen 함수를 통해서 문자열의 크기를 구했으므로 \n이 포함되지 않아서 7 Byte로 표시되었다.

* 배열은 끝을 알리기 위해서 프로그래머에게 보이지 않는 '\n'을 항상 덧붙인다.

 

또, MBCS의 문제는 하나 더 있다.

 

#include <stdio.h>

int main(void)
{
	char str[] = "한글입니다";
	int i = 0;

	for (; i < 5; ++i)
	{
		fputc(str[i], stdout);
	}

	fputs("\n", stdout);

	for (i = 0; i < 10; ++i)
	{
		fputc(str[i], stdout);
	}

	fputs("\n", stdout);

	return 0;
}

▶ 실행 결과

바로 확인하기 전에 위 코드가 어떤 결과를 가질지 생각해보자. MBCS 방식으로 표현되고 있기 때문에 5 글자 x 2 Byte로 총 문자열의 길이는 10 Byte가 될 것이다.

한글
한글입니다

 

fputc 함수는 1 Byte 데이터를 출력한다. 중간에 5 Byte까지만 출력을 요청했기 때문에 첫 출력에서는 '한글'( 4 Byte )로 잘려 나왔고 모든 Byte의 출력을 했을 때 정상적으로 문자열이 출력됨을 볼 수 있다. 이러한 문제들 때문에 모든 문자열을 2 Byte로 표현하는 WBCS 방식을 사용한다.

 

- WBCS 기반의 프로그래밍

WBCS 기반 프로그래밍은 몇 가지 변경되는 점들이 있다. 대표적으로 1 Byte 메모리 공간만 할당하는 char형 변수의 사용을 할 수 없고 이와 비슷한 사유로 인해서 기존 사용하는 함수에서 변경해야 하는 것들이 생긴다.

 

변경 전 변경 후 설명
char wchar_t char은 1 Byte 메모리 공간만 할당하기에 모든 문자열에 2 Byte를 사용하는
WBCS 방식에 알맞지 않다.

wchar_t는 아래와 같은 형태로 선언되어 있다.
typedef unsigned short wchar_t;
"ABC" L"ABC" wchar_t str[] = "ABC";

위와 같은 형태로 문자열을 선언한다면 문제가 생긴다. 배열 str은 유니코드 문자열을 저장할 준비가 되었으나, 대입하는 문자열이 MBCS 기반이기 때문이다.

이때에는 "ABC"를 L"ABC"로 교체해야 한다.
문자열 앞의 L은 유니코드 기반으로 표현하겠단 의미를 지닌다.
strlen wcslen 유니코드 문자열 계산을 위해서 wcslen으로 대체한다.

 

strlen과 wcslen

#include <stdio.h>
#include <string.h>

int main(void)
{
	wchar_t str[] = L"ABC";
	int size = sizeof(str);
	int len = wcslen(str);

	printf("Array Size : %d \n", size);
	printf("Character Length : %d", len);

	return 0;
}

▶ 실행 결과

Array Size : 8
Character Length : 3

문자열 조작 함수 대부분은 SBCS 기반 문자열을 처리하기 위한 함수였다. WBCS 기반 문자열 조작 함수에 대해서 살펴보는 것을 권장한다. 두 기반 함수의 매개 인자와 의미는 동일하다. 단순히 문자셋으로 생기는 차이가 있을 뿐이다.

 

- 완전한 유니코드 기반

Windows 2000 이상의 운영체제는 기본적으로 유니코드 기반으로 모든 문자열을 처리한다. 

 

printf("Hello World");

위 함수로 전달되는 문자열 "Hello World!"는 아스키 코드에 존재하는 문자들로 이루어져 있다. 그렇기 때문에 문자당 1 Byte로 표현된다. 만약 Windows 2000 이상의 운영체제에서 위와 같은 함수의 호출이 이뤄진다면, 운영체제는 전달 받은 문자열을 내부적으로 2 Byte 유니코드 형식으로 변환한다. 변환되는 과정으로 인해서 성능상에 문제가 생길 수 있으나, 다음과 같이 유니코드 기반 프로그램으로 작성하였다면 문제되지 않는다.

wprintf(L"Hello World!");

참고로 유니코드 기반 프로그램을 작성할 때에는 우리가 사용하는 main 함수가 아니라 wmain 함수에서 사용해야 한다. 이 두 함수의 차이는 프로그램 실행 시 전달되는 문자열을 유니코드 기반으로 구성한다는 점이다. main 함수에서도 유니코드 기반 프로그램 작성은 가능하나, 매개 인자가 SBCS 기반으로 넘어오므로 성능 상의 문제가 생길 수 있을 것 같다.

 

02. MBCS와 WBCS 동시 지원

현존하는 시스템 모두가 유니코드를 지원하는 것이 아니기 때문에 프로그램 개발 시, MBCS 기반과 WBCS 기반 중 하나를 선택해야 한다. 두 기반을 각각 개발한다면 고민할 필요가 없는 문제이므로 동시 지원을 하는 방법을 보자.

 

#window.h에 대해서
windows.h는 윈도우 프로그래밍에 필요한 다양한 종류의 헤더 파일을 포함하고 있다. CHAR과 WCHAR은 winnt.h에 정의가 되어 있고 winnt.h는 windef.h에 windef.h는 windows.h에 속해있다. 결론적으로 다음과 같다.

winnt.h ⊂ windef.h ⊂ windows.h

 

- 동시 지원을 위한 매크로

#ifdef _UNICODE
	#define		_tmain	wmain
	#define		_tsclen	wcslen
	#define		_tprintf wprintf
	...
#else
	#define		_tmain	main
	#define		_tmain	strlen
	#define		_tmain	printf
	...
#endif

위와 같이 매크로를 작성한다면 _UNICODE의 정의 유무에 따라서 WBCS 기반, MBCS 기반으로 컴파일 및 실행된다.

'독서 > 뇌를 자극하는 윈도우즈 시스템 프로그래밍' 카테고리의 다른 글

[스터디] 시스템 프로그래밍 - Chapter 5. 프로세스의 생성과 소멸  (0) 2023.10.02
[스터디] 시스템 프로그래밍 - Chapter 4. 컴퓨터 구조에 대한 두 번째 이야기  (1) 2023.09.19
[스터디] 시스템 프로그래밍 - Chapter 3. 64비트 기반 프로그래밍  (1) 2023.09.13
[스터디] 시스템 프로그래밍 - Chapter 1. 컴퓨터 구조에 대한 첫 번째 이야기  (1) 2023.09.11
[스터디] 시스템 프로그래밍 - 0  (0) 2023.09.11
'독서/뇌를 자극하는 윈도우즈 시스템 프로그래밍' 카테고리의 다른 글
  • [스터디] 시스템 프로그래밍 - Chapter 4. 컴퓨터 구조에 대한 두 번째 이야기
  • [스터디] 시스템 프로그래밍 - Chapter 3. 64비트 기반 프로그래밍
  • [스터디] 시스템 프로그래밍 - Chapter 1. 컴퓨터 구조에 대한 첫 번째 이야기
  • [스터디] 시스템 프로그래밍 - 0
태역
태역
  • 태역
    RYULAB
    태역
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • 언어
        • C
        • C++
        • C#
      • 엔진, 프레임워크
        • Unity
        • Unreal
        • Electron
      • 공부 N
        • 디자인 패턴
        • 수학
        • CS
        • Git
        • 알고리즘 N
        • 자료구조
      • 코테
        • 프로그래머스
        • 백준
      • 독서
        • Effective C#
        • CLR via C#
        • 뇌를 자극하는 윈도우즈 시스템 프로그래밍
        • 오브젝트
        • CSAPP
        • OSTEP
      • 프로젝트
        • Unity
      • 개발 일지
        • 퓨처리티
        • 골든타임
      • 활동
        • 게임잼 후기
        • 게임제작동아리 브릿지
        • 크래프톤 정글
        • 기타
      • 기타
  • 블로그 메뉴

    • 링크

    • 공지사항

      • 2024 04 17
    • 인기 글

    • 태그

      인프런 #인프런강의후기 #게임개발 #게임개발강의 #인강후기 #강의후기 #게임개발자 #인프런강의
      티스토리챌린지
      오블완
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    태역
    [스터디] 시스템 프로그래밍 - Chapter 2. 아스키코드 vs 유니코드
    상단으로

    티스토리툴바