[C++] 문자

2024. 3. 24. 20:55Programming 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-1616bit 단위를 사용하며, `U+FFFF`를 초과하는 문자를 표현하려면 서러게이트 페어라는 두 개의 단위가 필요하다.

반면, UTF-3232bit 단위로 모든 유니코드 문자를 처리하므로 이런 페어가 필요하지 않다.

 

3) 메모리 레이아웃이 간단하다.

• `char32_t`는 문자 하나가 정확히 하나의 유니코드에 대응하므로 문자열 인덱싱과 같은 작업이 단순하다.

문자열 인덱싱(string indexing)

• 문자열 내에서 각 문자의 인덱스(위치)를 사용하여 개별 문자로 접근하는 것

▶ 문자열 인덱싱 용도

1) 문자 접근 : 특정 위치의 문자를 가져오거나 비교할 때 사용한다.

2) 반복 작업 : 인덱스를 사용하여 문자열을 반복 처리한다.

3) 수정 작업 (가변 문자열) : 특정 위치의 문자를 변경한다. (ex. C++ 문자열 `std::string`)

 

※ 주의

UTF-8 같은 인코딩에서는 문자의 바이트 길이가 다를 수 있다.

단순히 인덱스로 접근한다고 해서 개별 문자를 정확히 가리키지 않을 수 있다.

  ex) "😊" (`U+1F60A`)는 UTF-8에서 4byte를 차지한다.