2024. 3. 24. 20:55ㆍProgramming Language/C++
아래 링크 클릭 시 해당 본문으로 이동
표현 방식이 정수형인 문자형
자료형 | 크기 (byte) |
char | 1 |
wchar_t | 2 |
char8_t | 1 |
char16_t | 2 |
char32_t | 4 |
• 문자에 해당하는 값을 저장하는 정수형이다.
• ASCII에 속하지 않는 문자(한글, 중국어, 이모지 등)는 `wchar_t`, `char16_t`, `char32_t`와 같은 문자형을 사용하며, UTF-16 또는 UTF-32와 같은 인코딩을 활용한다.
• C++에서는 유니코드 문자 처리를 위해 `char8_t`, `char16_t`, `char32_t`가 도입되었다.
이는 유니코드 인코딩에 최적화되어 있다.
VS 프로젝트 기본 속성은 유니코드이다.
(솔루션 탐색기에 <프로젝트명> - [구성 속성] - [고급])
문자
char | char* | char[] | |
역할 | 문자 하나 저장 | 문자를 가리키는 포인터 | 문자의 배열 (여러 문자 저장) |
용도 | 단일 문자 | 동적 문자열 처리 | 고정 크기 문자열 저장 |
크기 | 1byte | 포인터 크기 (4byte 또는 8byte) |
배열 길이에 따라 다르다. |
char
• 단일 문자를 표현하는 데 사용되며, 크기는 1byte이다.
• 정수를 대입하면 ASCII 코드로 해석한다.
ex) 65 = 'A'
#include <iostream>
using namespace std;
int main()
{
char c1 = 65;
cout << c1; // A
char c2 = 'A';
cout << c2; // A
return 0;
}
• 일반적으로 ASCII 코드값을 나타내지만 사용되는 인코딩은 플랫폼에 따라 달라질 수 있다.
(확장 ASCII 또는 UTF-8에서는 추가적으로 문자나 기호가 표현될 수 있다.)
저장할 수 있는 값 (char, unsigned char)
• (signed) char : -128 ~ 127
• unsigned char : 0 ~ 255
char*
• 문자를 가리키는 포인터
• C에서 문자열을 나타낼 때 많이 사용된다.
• 문자나 문자열의 주소를 저장하며, 문자열의 첫 번째 문자를 가리킨다.
▷ 예시
char* cp = "Hello World!" // cp는 문자열 "Hello World!"의 시작 주소를 가리킨다.
char[]
• 문자들의 배열
• 고정된 크기의 문자열을 저장하는 데 사용된다.
• 주소에 접근하는 것이 아니라서 `char*`과 다르게 문자열 하나하나 수정할 수 있다.
• 문자열 끝에는 항상 `'\0'`(NULL 문자)가 추가되어 문자열의 끝을 표시한다.
• 초기화할 때 배열의 크기는 NULL 문자 `'\0'`를 포함한 문자열의 길이에 따라 자동으로 결정된다.
• 초기화하지 않는 경우에는 배열의 크기를 명시해야 한다.
▷ 예시
// 초기화할 때
char carr[] = "Happy"; // {'H', 'a', 'p', 'p', 'y', '\0'} 저장
// 초기화하지 않을 때 => 크기를 명시해줘야 한다.
char carr2[10]; // 크기가 10인 배열
wchar_t
• 와이드 문자(wide character, 확장 문자, 2byte(16bit) 크기의 다국어 문자 코드)를 저장하는 2byte 크기의 문자형이다.
`wchar_t`는 `char`보다 더 넓은 범위의 값을 저장한다.
8bit(1byte)일 때 표현 가능한 경우의 수 : 2^8 = 256
16bit(2byte)일 때 표현 가능한 경우의 수 : 2^16 = 65536
문자 하나를 2byte로 표현하면 훨씬 더 많은 문자를 표현할 수 있다.
• 정수를 대입하면 유니코드(Unicode)로 해석한다.
• 플랫폼에 따라 16bit 또는 32bit 범위의 값을 저장할 수 있고, 이를 통해 UTF-16 또는 UTF-32와 같은 문자 인코딩을 지원한다.
즉, `wchar_t`의 크기와 인코딩은 플랫폼마다 다르다.
▶ Windows : 16bit이며, 주로 UTF-16을 사용한다.
▶ Unix/Linux : 32bit이며, 주로 UTF-32를 사용한다.
• 배열을 사용하여 초기화하고, 문자 또는 문자열 앞에 `L`을 붙인다.
접두사 `L`은 `wchar_t` 타입임을 나타낸다.
// L'문자'
L'a'
// L"문자열"
L"abc"
`wchar_t` 초기화
// 문자 자료형만 가능한 초기화 방법
wchar_t 배열변수명[배열길이] = L"문자열";
▷ 주의할 점
int main(){
// wchar_t 초기화할 때 실수하는 경우
// 1. 문자열 앞에 L을 붙이지 않은 경우
wchar_t wc = "459"; // 오류
// 2. 배열을 사용하지 않은 경우
wchar_t wc = L"abcdef"; // 오류
// 3. " "를 ' '로 적은 경우
// 오류는 아니지만 ' '는 문자를 의미하기 때문에 맨 앞 문자 하나만 저장된다.
wchar_t wc = L'abcdef'; // 97'a'
return 0;
}
문자의 끝을 의미하는 숫자 0
메모리상으로 문자열 맨 뒤에 있는 0은 마침표의 역할을 한다.
메모리에서 0이 읽히면 그전까지의 문자를 반영하여 저장한다.
▷ "459"
`'\0'`는 아무것도 없는 빈 문자인 널(NULL) 문자를 의미한다.
52 | 53 | 57 | 0 | ⋯ |
만약 0이 없다면 문자의 끝이 정해지지 않아서 원하는 문자를 저장할 수 없는 문제가 발생한다.
30 | 36 | 42 | ⋯ | 10 | ⋯ |
※ 문자열 뒤에 오는 0까지 생각해서 배열의 길이를 여유 있게 설정해야 한다.
▷ 예시
// 배열의 전체 메모리 크기 = 2byte 단위 x 10개 = 20byte
wchar_t wchar[10] = L"abcdef";
a | b | c | d | e | f | 0 |
메모리 상으로 7칸 필요하지만, 만약 0을 생각하지 않고 배열의 길이를 원래 길이보다 부족하게 설정하면 오류가 발생한다.
wchar_t wchar[6] = L"abcdef"; // 오류
타입 | 크기 (byte) | 인코딩 | 용도 |
char8_t | 1 | UTF-8 | 유니코드의 간결한 인코딩, 파일 또는 통신에 적합하다. |
char16_t | 2 | UTF-16 | Windows처럼 UTF-16을 지원하는 플랫폼에서 사용한다. |
char32_t | 4 | UTF-32 | 모든 유니코드 문자를 직접 표현할 수 있다. |
char8_t
• C++20에서 도입된 문자형으로, UTF-8 문자를 표현한다.
• `char`와 크기는 8bit로 같지만, 유형이 다르다.
• 목적 : UTF-8 데이터임을 명시적으로 나타내어 코드의 명확성과 안전성을 높인다.
`char16_t`, `char32_t`는 C++11에서 도입된 문자형이다.
char16_t
• 16bit 유니코드 문자를 표현한다.
• 주로 UTF-16 인코딩으로 문자를 저장하는 데 사용된다.
• UTF-16 인코딩에 맞는 문자를 표현할 수 있다.
• 유니코드의 BMP 영역 문자를 처리하며, BMP 외부 문자는 서러게이터 페어로 처리한다.
BMP (Basic Multilingual Plane, 다국어 기본 평면)
• 유니코드에서 가장 첫 번째 평면으로, 코드 포인트가 `U+0000`~`U+FFFF` 사이에 위치한다.
▷ 유니코드 다국어 기본 평면 그림
1칸당 256자를 나타낸다.
• 범위 : 16bit로 표현 가능한 65,536개의 문자
• 특징 : 대부분 문자(한글, 라틴 문자, 수학 기호 등)를 포함한다.
ex) 라틴 알파벳 : `U+0041`(A), `U+005A`(Z)
한글 : `U+AC00` ~ `U+005A`
중국어 : `U+4E00` ~ `U+9FFF`
Surrogate Pair(서러게이트 페어)
• UTF-16에서 BMP 범위 밖의 문자(코드 포인트 `U+10000` 이상)를 표현하기 위해 16bit 값을 2개로 조합하여
나의 문자를 나타내는 방법이다.
▼ 작동 원리
고위 서러 게이트 (High Surrogate) : `U+D800` ~ `U+DBFF`
저위 서러 게이트 (Low Surrogate) : `U+DC00` ~ `U+DFFF`
• 두 값을 결합하여 하나의 32bit 유니코드 문자를 표현한다.
char32_t
• 32bit 유니코드 문자를 표현한다.
• UTF-32 인코딩으로 문자를 저장하는 데 사용된다.
• 유니코드 표준에 있는 모든 문자를 표현할 수 있다.
UTF-32는 모든 유니코드 문자를 단일 4byte 값으로 표현할 수 있기 때문이다.
char32_t에서 서러게이트 페어가 필요 없는 이유
1) 모든 유니코드 코드를 직접 표현할 수 있다.
• UTF-32는 32bit를 사용하여 `U+0000`~`U+10FFFF`까지의 모든 유니코드를 직접 표현할 수 있다.
때문에 추가적인 서러게이트 페어가 필요하지 않다.
2) 문자 분할이 필요 없다.
UTF-16은 16bit 단위를 사용하며, `U+FFFF`를 초과하는 문자를 표현하려면 서러게이트 페어라는 두 개의 단위가 필요하다.
반면, UTF-32는 32bit 단위로 모든 유니코드 문자를 처리하므로 이런 페어가 필요하지 않다.
3) 메모리 레이아웃이 간단하다.
• `char32_t`는 문자 하나가 정확히 하나의 유니코드에 대응하므로 문자열 인덱싱과 같은 작업이 단순하다.
문자열 인덱싱(string indexing)
• 문자열 내에서 각 문자의 인덱스(위치)를 사용하여 개별 문자로 접근하는 것
▶ 문자열 인덱싱 용도
1) 문자 접근 : 특정 위치의 문자를 가져오거나 비교할 때 사용한다.
2) 반복 작업 : 인덱스를 사용하여 문자열을 반복 처리한다.
3) 수정 작업 (가변 문자열) : 특정 위치의 문자를 변경한다. (ex. C++ 문자열 `std::string`)
※ 주의
UTF-8 같은 인코딩에서는 문자의 바이트 길이가 다를 수 있다.
단순히 인덱스로 접근한다고 해서 개별 문자를 정확히 가리키지 않을 수 있다.
ex) "😊" (`U+1F60A`)는 UTF-8에서 4byte를 차지한다.
'Programming Language > C++' 카테고리의 다른 글
[C++] 스트림(stream), 버퍼(buffer) (0) | 2024.03.26 |
---|---|
[C++] 주석(Comment), 세미콜론(;) (0) | 2024.03.25 |
[C++ STL] 벡터(vector), 리스트(list) (0) | 2024.03.19 |
[C++] namespace, using, 입출력 구현 (cin, cout) (0) | 2024.03.19 |
[C++] 구조체 · 클래스 템플릿으로 리스트 구현 (0) | 2024.03.18 |