신입 게임 개발자의 프로그래밍 일기
[C++ 입문자에서 벗어나기]Chapter_1: 타입(Type)#3 본문
[C++ 입문자에서 벗어나기]Chapter_1: 타입(Type)#3
이번 포스팅에서는 문자와 문자열 그리고 typedef 사용법에 대해서 이야기해 볼 것입니다.
더불어 참조타입에 대해서도 이야기하겠지만 간단히 언급만하고 넘어가겠습니다.
참조타입은 추후에 자세히 이야기하겠습니다.
[문자 타입]
C/C++에서 기본적으로 문자들을 표현하기 위해서 char 타입을 사용해왔습니다.
이 char 타입은 ASCII 인코딩 방식을 사용하여 문자들을 비트 상태들과 대응시키는데
우선, ASCII에 대해서 간단히 살펴봅시다.
[ASCII & 멀티바이트 문자 집합(MBCS)]
ASCII는 영문 알파벳을 디지털화시키기 위해 사용되는 대표적인 7비트 문자 인코딩입니다.
7비트를 사용하는 ISO/IEC 646 나 8비트를 사용하는 ISO 8859와 같이 ASCII를 기반으로 한 확장 인코딩들이 존재하는데 이 확장 인코딩들은 언어 군에 따라서 같은 숫자에 서로 다른 문자를 배당시킴으로 영어 이외의 문자들의 표현이 가능하도록 만들었습니다.
하지만 기본적인 ASCII 방식만으로는 모든 문자의 인코딩이 가능한 것은 아니었습니다.
알파벳은 총 128개라서 7개의 비트만으로 전부 표현이 가능하지만 한국어를 비롯한 중국어 등의 문자 집합은 싱글바이트(1Byte)로는 표현이 불가능합니다. 이를 해결하기 위해 멀티바이트(2Byte) 문자 집합이 제안됩니다. 멀티바이트 문자 집합은 기존 ASCII를 호환하면서 싱글바이트로 표현이 불가능했던 문자들을 표현가능하도록 하였는데 그것을 가능하게한 방식은 아래와 같습니다.
첫번째 바이트의 비트를 검사하여 비트의 값이 128이하일 경우에는 싱글바이트로 취급하여 ASCII로 그 비트들을 처리합니다.
만약 비트의 값이 128을 넘어갈 경우, 그 다음 바이트까지 합친 2byte를 활용하여 멀티바이트 문자 집합으로 비트들을 처리합니다.
하지만 소프트웨어들이 국제화가 되어가면서 각 문화권에 따라서 다른 코드페이지를 이용하여 인코딩을 하는 ASCII방식(MBCS포함)에 언어별 호환성에 대한 제약이라는 어려움이 나타나게 됩니다.
이것을 해결하기 위하여 "이 세상 모든 문자를 단일 코드로 통합하려는 움직임"이 시작됩니다.
[유니코드(Unicode)]
유니코드는 이 세상 모든 문자들에게 유일한 코드를 부여한 것으로
이를 통해 언어군에 따라 동일한 코드가 다른 문자로 표시되는 문제점이 사라지게 됩니다.
유니코드를 접해보신 분들은 UTF-N 방식으로 유니코드들이 여러 개가 있는 것을 아실 겁니다.
UTF은 Unicode Transformation Format의 약자로 뒤에 붙여진 N은 유니코드 인코딩 시 사용되는 비트의 개수를 뜻합니다.
이 비트의 개수는 각 문화권에 따라 선호도가 다른데 알파벳을 사용하는 문화권은 UTF-8을 선호합니다.
그 이유는 ASCII와 호환이 되면서 알파벳이 1바이트만을 사용하기 때문입니다.
반면 한글을 사용하는 우리나라는 UTF-16을 선호합니다.
그 이유는 UTF-8에서 한글은 3Byte로 처리되지만 UTF-16에서 한글은 2Byte로 처리되기 때문입니다.
추가적으로 UTF-8은 글자의 수를 셀 경우, 각 글자마다 바이트 크기가 달라서 많은 연산을 요구하게 됩니다.
|
UTF-8
|
UTF-16
|
UTF-32
|
영어
|
1Byte
|
2Byte
|
4Byte
|
한글
|
3Byte
|
2Byte
|
4Byte
|
[wchar_t 타입]
C++에서는 유니코드를 지원하기 위하여 wchar_t라는 타입을 제공하고 있습니다.
이 때 사용되는 유니코드 인코딩 방식은 UTF-16 or UTF-32인데 두개로 나뉘는 이유는
컴파일러에 따라 인코딩시 사용되는 비트의 개수가 달라지기 때문입니다.
VC++은 2바이트를 이용하는 UTF-16을 지원하면 GCC는 4바이트를 이용하는 UTF-32를 지원합니다.
문자열 상수에서 이 문자열이 WideCharacter임을 컴파일러에게 알리기 위해 L매크로를 이용할 수도 있습니다.
[문자열]
C/C++은 기본적으로 문자열 타입을 제공하지는 않습니다.
기본적인 타입으로 제공하지 않을뿐 아래 나열된 것들과 같이 라이브러리 형태로 제공됩니다.
- CString: VC++에서 지원하는 라이브러리
- string: C++ 표준 라이브러리, 문자를 char(1바이트)로 처리
- wstring: C++ 표준 라이브러리, 문자를 wchar_t(컴파일러에 다라 다름)로 처리
C/C++에서 문자열을 주료 표현하는 BSTR(Basic string or binary String)이라는
NULL로 문자열의 끝을 알리는 방식으로 베이직이나 파스칼 및 윈도우 COM에서도
사용되는 문자열 표현 방식입니다.
[참조 타입]
참조 타입에 대해 설명하실 "참조 타입은 별칭(alias)이다." 라는 표현을 많이 사용합니다.
하지만 이 말에는 오류가 있습니다.
컴파일러가 최적화를 하지 않을 시에는 참조 타입도 포인터와 같이 동작합니다.
이 말의 뜻은 포인터처럼 메모리 공간을 차지한다는 겁니다.
*포인터의 크기는 Ubuntu-64비트임으로 8바이트를 차지함을 참고하세요
(int a = 5: )
movl $5, -20(%rbp) <= -20(%rbp)번지에 5라는 값을 저장;
(int* b = &a;)
leaq -20(%rbp), %rax <= -20(%rbp)번지(변수 a의 주소값)를 rax레지스터에 저장
movq %rax, -16(%rbp) <= -16(%rbp)번지에 rax레지스터에 저장된 주소값을 저장
(int& c = a;)
leaq -20(%rbp), %rax <= -20(%rbp)번지(변수 a의 주소값)를 rax레지스터에 저장
movq %rax, -8(%rbp) <= -8(%rbp)번지에 rax레지스터에 저장된 주소값을 저장
어셈블리 코드에서 확인할 수 있듯이 참조 타입도 기본적으로는 포인터로 동작합니다.
단지 컴파일러의 최적화 여부에 따라 포인터와 같이 메모리 공간을 차지할 지
혹은 단순 별칭으로 처리될지가 결정될 뿐입니다.
(C++ 프로그래밍 언어[저자: 비야네 스트롭스트룹, 출판년도: 2005년]의 5.5 참조자 지문 중 일부 발췌)
컴파일러에 따라 참조자를 최적화시켜 버림으로써 런타임에 참조자를 위한 객체가 생기지 않도록하기도 한다.
[키워드: typedef]
이번에는 C++에서 많이 사용되는 typedef에 대해 알아보겠습니다.
#define 전처리문과 같이 이미 알려진 타입을 새로운 이름으로 정의할 때 사용되는 키워드이지만
유효범위 설정이라는 기능 또한 가지고 있습니다.
정의 방법은 아래와 같습니다.
1. 원하는 타입을 선언한다.
2. 선언문 앞에 typedef를 붙인다.
3. 선언문의 객체 이름을 정의하고자 하는 타입 이름으로 변경한다.
이 정의 방법에 따라 배열과 함수 포인터를 typedef 키워드를 활용해봅시다.
(배열)
1. Player player[5]; //배열을 선언합니다.
2. typedef Player player[3]; //선언문 앞에 typedef 키워드를 붙입니다.
3. typedef Player ARRAY_PLAYER_FIVE[5]; //선언문의 객체 이름을 새롭게 정의하고자 하는 타입 이름으로 변경합니다.
(함수 포인터)
1. void (*damaged) (int power); //함수 포인터를 선언합니다.
2. typedef void (*damaged) (int power); //선언문 앞에 typedef 키워드를 붙입니다.
3. typedef void (*DAMAGED) (int power); //선언문의 함수 이름을 새롭게 정의하고자 하는 타입 이름으로 변경합니다.
이로써 타입에 대한 포스팅이 끝났습니다.
다음번 포스팅부터는 선언과 정의에 대해 이야기해보겠습니다.
'Language > C++' 카테고리의 다른 글
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#2 (0) | 2017.11.08 |
---|---|
[C++ 입문자에서 벗어나기]Chapter_2: 선언과 정의#1 (0) | 2017.11.05 |
[C++ 입문자에서 벗어나기]Chapter_1: 타입(Type)#2 (0) | 2017.11.03 |
[C++ 입문자에서 벗어나기]Chapter_1: 타입(Type)#1 (0) | 2017.10.17 |
[C++ 입문자에서 벗어나기]Chapter_0: 목표(갱신: 2017년 10월 17일 목요일) (0) | 2017.10.17 |