C++ 문자열이란? 문자 배열과 포인터로 이해하는 C 스타일 문자열

앞선 글에서는 같은 타입의 여러 데이터를 배열에 저장하는 방법과 배열 이름이 대부분의 표현식에서 첫 번째 원소를 가리키는 포인터로 변환되는 과정을 알아보았습니다.

문자열도 이러한 배열과 포인터의 개념을 바탕으로 표현할 수 있습니다.

const char* name = "Ronnie";

문자열(String)은 문자가 연속해서 저장된 데이터입니다. C 스타일 문자열은 마지막에 null 문자 '\0'를 저장해 문자열의 끝을 구분합니다.

이번 글에서는 std::string보다 문자 배열과 포인터로 표현하는 C 스타일 문자열(C-style String)의 구조를 중심으로 살펴보겠습니다.

이 구조를 이해하면 언리얼 엔진에서 TCHAR, TEXT(), FString을 사용하는 이유와 문자열 변환 과정도 이해하기 쉬워집니다.

C 스타일 문자열을 비공식적으로 raw 문자열이라고 표현하기도 하지만, C++에서 정식으로 Raw String Literal이라고 부르는 R"(…)" 문법과는 다른 개념입니다.


문자 인코딩이란?

컴퓨터는 문자 자체를 직접 저장하지 않고, 각 문자에 대응하는 숫자를 저장합니다.

char grade = 'A';

std::cout << static_cast<int>(grade) << '\n';

일반적인 ASCII 호환 환경에서 문자 'A'에 대응하는 숫자는 65입니다.

문자와 숫자를 어떤 규칙으로 대응시킬지 정의한 것을 문자 인코딩(Character Encoding)이라고 합니다.

ASCII

ASCII는 영문 알파벳과 숫자, 일부 기호 및 제어 문자를 정의한 문자 인코딩입니다.

  • 영문 대문자와 소문자
  • 숫자 0부터 9
  • 공백 및 일부 특수 기호
  • 줄바꿈과 같은 제어 문자

ASCII만으로는 한글을 비롯한 세계 여러 언어의 문자를 표현할 수 없습니다.

Unicode와 UTF 인코딩

세계 여러 언어의 문자를 일관되게 다루기 위해 Unicode가 사용됩니다. Unicode 문자 값을 실제 바이트로 저장하는 대표적인 방식에는 UTF-8과 UTF-16 등이 있습니다.

  • Unicode: 각 문자에 고유한 코드 포인트를 부여하는 표준
  • UTF-8: 하나의 Unicode 문자를 1~4바이트로 표현하는 인코딩
  • UTF-16: 하나의 Unicode 문자를 하나 또는 두 개의 16비트 코드 단위로 표현하는 인코딩

문자 타입의 크기와 문자 인코딩은 같은 개념이 아닙니다.

char의 크기가 1바이트라고 해서 반드시 ASCII 문자만 저장하는 것은 아닙니다. UTF-8 문자열도 여러 char 값의 연속으로 저장할 수 있습니다.

반대로 wchar_t를 사용한다고 해서 모든 플랫폼에서 같은 인코딩을 사용하거나 모든 문자 문제가 자동으로 해결되는 것도 아닙니다.

문자열을 다룰 때는 다음 항목을 구분해서 이해해야 합니다.

  • 문자 타입의 크기
  • 메모리에 저장된 코드 단위
  • 사용 중인 문자 인코딩
  • 문자열을 해석하거나 출력하는 환경

참고 자료: ASCII Table

관련 발표: CppCon 2014: James McNellis, Unicode in C++


문자와 문자열

하나의 문자는 char와 같은 문자 타입으로 표현할 수 있습니다.

char grade = 'A';

문자 리터럴은 작은따옴표로 감쌉니다.

여러 문자가 연속해서 저장된 문자열 리터럴은 큰따옴표로 감쌉니다.

const char* name = "Ronnie";
구분 예제 의미
문자 리터럴 'A' 하나의 문자
문자열 리터럴 "Ronnie" null 문자로 끝나는 문자 배열

'A'"A"는 서로 다릅니다.

char character = 'A';
const char* string = "A";

'A'는 하나의 문자 값입니다. "A"는 문자 'A'와 문자열의 끝을 나타내는 '\0'가 저장된 문자열 리터럴입니다.


문자열 리터럴의 구조

문자열 리터럴 "Ronnie"는 개념적으로 다음과 같은 문자 배열로 저장됩니다.

인덱스 0 1 2 3 4 5 6
'R' 'o' 'n' 'n' 'i' 'e' '\0'

화면에 표시되는 문자는 6개지만 마지막에 null 문자가 추가되므로 총 7개의 char가 필요합니다.

C++에서 일반적인 문자열 리터럴 "Ronnie"의 타입은 const char[7]입니다.

const char text[] = "Ronnie";

문자열 리터럴은 배열이지만 대부분의 표현식에서는 첫 번째 문자를 가리키는 const char*로 변환됩니다.

const char* name = "Ronnie";

null 문자가 필요한 이유

C 스타일 문자열은 별도의 길이 정보를 문자열 데이터에 포함하지 않습니다.

대신 마지막에 저장된 null 문자 '\0'를 이용해 문자열의 끝을 구분합니다.

char name[] = { 'R', 'o', 'n', 'n', 'i', 'e', '\0' };

C 스타일 문자열을 처리하는 함수는 일반적으로 첫 번째 문자부터 시작해 null 문자를 만날 때까지 문자를 읽습니다.

std::cout << name << '\n';

std::cout은 다음 순서로 문자를 읽습니다.

  1. 'R'부터 문자를 차례대로 읽습니다.
  2. '\0'를 만나면 문자열의 끝으로 판단합니다.
  3. null 문자 앞까지의 문자를 출력합니다.

null 문자의 값은 숫자 0입니다. 문자로 표현할 때는 '\0'를 사용합니다.

null 문자 '\0'는 숫자 문자 '0'과 다릅니다. '0'는 화면에 표시할 수 있는 숫자 모양의 문자이고, '\0'는 값이 0인 문자열 종료 문자입니다.


const char*로 문자열 가리키기

문자열 리터럴은 대부분의 표현식에서 첫 번째 문자를 가리키는 포인터로 변환됩니다.

const char* name = "Ronnie";

name에는 문자열 리터럴의 첫 번째 문자인 'R'의 주소가 저장됩니다.

문자열 리터럴은 수정할 수 없으므로 const char*로 가리켜야 합니다.

#include <iostream>

int main()
{
    const char* name = "Ronnie";

    std::cout << name << '\n';
    std::cout << name[0] << '\n';

    std::cin.get();
}

출력 결과

Ronnie
R

std::cout에 일반적인 포인터를 전달하면 주소가 출력될 수 있습니다.

하지만 const char* 또는 char*를 전달하면 C 스타일 문자열로 처리합니다. 해당 주소부터 null 문자를 만날 때까지의 문자를 출력합니다.

첫 번째 원소에는 배열의 인덱스 문법으로 접근할 수 있습니다.

name[0]

이는 다음 포인터 표현식과 같은 문자에 접근합니다.

*(name + 0)

문자열 리터럴은 수정하지 않는다

문자열 리터럴을 수정 가능한 char*에 저장하는 코드는 현대 C++에서 허용되지 않습니다.

// char* name = "Ronnie"; // 오류

const_cast 등을 사용해 강제로 const를 제거하더라도 문자열 리터럴을 수정하면 정의되지 않은 동작이 발생합니다.

const char* name = "Ronnie";

// name[0] = 'B'; // 오류

수정 가능한 char 배열 만들기

수정 가능한 C 스타일 문자열이 필요하다면 문자열 리터럴을 이용해 char 배열을 초기화할 수 있습니다.

char name[] = "Ronnie";

컴파일러는 마지막 null 문자까지 포함해 배열의 크기를 결정합니다. 따라서 위 배열의 크기는 7입니다.

문자열 리터럴의 각 문자가 배열에 복사되어 저장되므로 배열의 원소를 변경할 수 있습니다.

#include <iostream>

int main()
{
    char name[] = "Ronnie";

    name[0] = 'B';

    std::cout << name << '\n';

    std::cin.get();
}

출력 결과

Bonnie

다음 두 선언은 비슷해 보이지만 저장 방식과 수정 가능 여부가 다릅니다.

const char* firstName = "Ronnie";
char secondName[] = "Ronnie";
선언 의미 문자 변경
const char* firstName 문자열 리터럴의 시작 주소를 저장 불가능
char secondName[] 문자열 내용을 배열에 복사해 저장 가능

null 문자가 없는 문자 배열

모든 문자 배열이 C 스타일 문자열인 것은 아닙니다.

char name[6] = { 'R', 'o', 'n', 'n', 'i', 'e' };

위 배열에는 문자 6개만 저장되어 있고 문자열의 끝을 나타내는 null 문자가 없습니다.

이 배열을 C 스타일 문자열이 필요한 곳에 전달하면 문제가 발생합니다.

#include <iostream>

int main()
{
    char name[6] = { 'R', 'o', 'n', 'n', 'i', 'e' };

    std::cout << name << '\n'; // 정의되지 않은 동작

    std::cin.get();
}

std::cout은 null 문자를 만날 때까지 문자를 계속 읽으려고 합니다.

그러나 name 배열 안에는 null 문자가 없으므로 배열의 범위를 벗어난 메모리까지 읽게 됩니다. 이러한 접근은 정의되지 않은 동작을 발생시킵니다.

  • 문자열 뒤에 의미 없는 문자가 함께 출력될 수 있습니다.
  • 우연히 정상적인 문자열처럼 출력될 수도 있습니다.
  • 프로그램이 비정상적으로 동작할 수 있습니다.

배열의 크기를 하나 늘리고 마지막에 null 문자를 추가하면 올바른 C 스타일 문자열이 됩니다.

char name[7] = { 'R', 'o', 'n', 'n', 'i', 'e', '\0' };

문자열 리터럴을 사용하면 컴파일러가 마지막 null 문자를 자동으로 추가합니다.

char name[] = "Ronnie";

문자와 문자 배열 비교하기

하나의 문자와 C 스타일 문자열을 함께 비교해보겠습니다.

#include <iostream>

int main()
{
    char character = 'A';

    char firstString[] = "Hello World";

    char secondString[6];
    secondString[0] = 'H';
    secondString[1] = 'e';
    secondString[2] = 'l';
    secondString[3] = 'l';
    secondString[4] = 'o';
    secondString[5] = '\0';

    size_t count = sizeof(firstString) / sizeof(firstString[0]);

    for (size_t index = 0; index < count - 1; ++index)
    {
        std::cout << firstString[index];
    }

    std::cout << '\n';
    std::cout << character << ", "
        << firstString << ", "
        << secondString << '\n';

    std::cin.get();
}

firstString에는 화면에 보이는 11개의 문자와 마지막 null 문자가 저장됩니다.

"Hello World"의 문자 수: 11
배열에 필요한 원소 수: 12

sizeof(firstString)에는 마지막 null 문자도 포함됩니다.

반복문에서 count - 1까지만 순회하는 이유는 마지막 null 문자를 일반 문자 출력 대상에서 제외하기 위해서입니다.

배열의 인덱스 표현식은 포인터 연산으로도 나타낼 수 있습니다.

firstString[index]
*(firstString + index)

두 표현식은 같은 문자에 접근합니다.


sizeof와 strlen의 차이

문자 배열의 크기와 C 스타일 문자열의 길이는 서로 다른 개념입니다.

sizeof는 배열 전체의 바이트 크기를 구합니다.

std::strlen은 첫 번째 문자부터 null 문자 앞까지의 문자 개수를 구합니다.

#include <cstring>
#include <iostream>

int main()
{
    char name[] = "Ronnie";

    std::cout << sizeof(name) << '\n';
    std::cout << std::strlen(name) << '\n';

    std::cin.get();
}

출력 결과

7
6
표현식 결과 null 문자 포함
sizeof(name) 배열 전체 크기인 7바이트 포함
std::strlen(name) 문자열 길이인 6 포함하지 않음

sizeof(name)이 배열 전체 크기를 반환하는 이유는 이 위치에서 name이 실제 배열이기 때문입니다.

배열이 포인터로 변환된 뒤에는 sizeof로 문자열이나 배열의 길이를 구할 수 없습니다.

const char* name = "Ronnie";

std::cout << sizeof(name) << '\n';

위 코드의 sizeof(name)은 문자열 크기가 아니라 포인터 변수의 크기를 반환합니다.

std::strlen은 null 문자를 찾을 때까지 메모리를 읽습니다. 반드시 올바르게 null 문자로 끝나는 문자열을 전달해야 합니다.


문자열을 동적으로 할당하기

실행 중에 필요한 문자열의 길이를 확인하고 그 크기에 맞는 문자 배열을 동적으로 할당할 수 있습니다.

const char* source = "Ronnie";

size_t length = std::strlen(source) + 1;
char* copiedString = new char[length];

std::strlen(source)은 null 문자를 제외한 문자 개수를 반환합니다.

따라서 마지막 null 문자를 저장할 공간을 확보하려면 1을 더해야 합니다.

문자 개수: 6
null 문자 공간: 1
필요한 배열 크기: 7

문자열을 복사한 뒤에는 copiedString이 별도의 문자 배열을 가리킵니다.

new[]로 할당한 문자 배열은 사용이 끝난 뒤 delete[]로 해제해야 합니다.

delete[] copiedString;
copiedString = nullptr;

해제하지 않으면 메모리 누수가 발생할 수 있습니다.


클래스가 문자열을 소유하는 방법

클래스가 생성자로 전달받은 문자열을 독립적으로 보관하려면 필요한 크기의 문자 배열을 할당하고 문자열을 복사할 수 있습니다.

#include <cstring>
#include <iostream>

class Person
{
public:
    Person(const char* inputName)
    {
        size_t length = std::strlen(inputName) + 1;

        name = new char[length];
        strcpy_s(name, length, inputName);
    }

    ~Person()
    {
        delete[] name;
    }

    Person(const Person&) = delete;
    Person& operator=(const Person&) = delete;

    void PrintName() const
    {
        std::cout << "이름: " << name << '\n';
    }

private:
    char* name = nullptr;
};

int main()
{
    Person* person = new Person("Ronnie");

    person->PrintName();

    delete person;
    person = nullptr;

    std::cin.get();
}

생성자 매개변수 inputName은 전달받은 문자열을 읽기만 하므로 const char*로 선언했습니다.

Person(const char* inputName)

멤버 변수 name은 새로 할당한 수정 가능한 문자 배열의 시작 주소를 저장합니다.

char* name = nullptr;

필요한 배열 크기는 문자열의 길이에 null 문자 하나를 더해 계산합니다.

size_t length = std::strlen(inputName) + 1;

생성자에서 할당한 메모리는 소멸자에서 해제합니다.

~Person()
{
    delete[] name;
}

delete person을 호출하면 Person 객체의 소멸자가 실행되고, 소멸자 안에서 내부 문자 배열도 해제됩니다.

객체 복사를 막은 이유

Person은 동적으로 할당한 메모리를 직접 소유합니다. 컴파일러가 기본으로 생성하는 복사 기능을 사용하면 포인터에 저장된 주소만 복사될 수 있습니다.

Person first("Ronnie");
// Person second = first;

주소만 복사되면 두 객체가 같은 문자 배열을 가리키게 됩니다. 두 객체의 소멸자가 같은 메모리에 delete[]를 호출하면 이중 해제 문제가 발생할 수 있습니다.

이 예제에서는 단순 복사를 방지하기 위해 복사 생성자와 복사 대입 연산자를 삭제했습니다.

Person(const Person&) = delete;
Person& operator=(const Person&) = delete;

객체 복사를 지원하려면 각 객체가 별도의 문자 배열을 가지도록 복사 생성자와 복사 대입 연산자를 직접 구현해야 합니다.

이 예제는 C 스타일 문자열의 동적 할당과 객체의 메모리 소유 관계를 이해하기 위한 코드입니다. 실제 코드에서는 직접 문자 배열을 관리하기보다 std::string을 멤버로 사용하는 것이 일반적입니다.


strcpy_s로 문자열 복사하기

strcpy_s는 원본 C 스타일 문자열을 수정 가능한 목적지 문자 배열로 복사할 때 사용할 수 있는 함수입니다.

errno_t strcpy_s(
    char* destination,
    size_t destinationSize,
    const char* source
);
매개변수 의미
destination 복사된 문자열을 저장할 문자 배열
destinationSize null 문자 공간까지 포함한 목적지 배열의 전체 크기
source 복사할 원본 C 스타일 문자열

문자열을 복사하기 전에 목적지 배열에 충분한 공간을 확보해야 합니다.

size_t length = std::strlen(inputName) + 1;

name = new char[length];
strcpy_s(name, length, inputName);

destinationSize에는 실제로 할당한 배열의 전체 크기를 전달합니다. 마지막 null 문자를 저장할 공간도 포함해야 합니다.

strcpy_s는 Microsoft Visual C++에서 사용할 수 있지만, 모든 C++ 컴파일러에서 동일하게 제공되는 이식 가능한 표준 함수라고 가정해서는 안 됩니다.

플랫폼에 따라 지원 여부와 함수 형태가 다를 수 있으므로 여러 플랫폼을 대상으로 한다면 해당 환경에서 제공하는 함수나 표준 문자열 클래스를 사용해야 합니다.


wchar_t와 넓은 문자열

wchar_t는 넓은 문자(Wide Character)를 표현하기 위한 문자 타입입니다.

wchar_t 문자열 리터럴을 작성할 때는 큰따옴표 앞에 대문자 L을 붙입니다.

const wchar_t* wideName = L"Ronnie";

넓은 문자열은 std::wcout으로 출력할 수 있습니다.

#include <iostream>

int main()
{
    const wchar_t* wideName = L"Ronnie";

    std::wcout << wideName << L'\n';

    std::cin.get();
}

wchar_t의 크기는 플랫폼에 따라 다를 수 있습니다.

  • Windows 환경에서는 일반적으로 2바이트입니다.
  • Linux 계열 환경에서는 일반적으로 4바이트입니다.

정확한 크기는 sizeof로 확인할 수 있습니다.

std::cout << sizeof(wchar_t) << '\n';

wchar_t를 사용한다고 해서 모든 환경의 문자 인코딩 문제가 자동으로 해결되지는 않습니다. 문자 타입의 크기와 실제 문자열 인코딩은 구분해서 이해해야 합니다.


언리얼 엔진의 문자열

언리얼 엔진에서는 플랫폼에 따른 문자 표현의 차이를 처리하기 위해 TCHAR 타입과 TEXT() 매크로를 사용합니다.

const TCHAR* characterName = TEXT("Ronnie");
  • TCHAR는 언리얼 엔진의 문자 타입입니다.
  • TEXT()는 문자열 리터럴을 언리얼 엔진에서 사용하는 문자 타입에 맞게 표현합니다.
  • const TCHAR*는 null 문자로 끝나는 TCHAR 배열의 시작 위치를 가리킵니다.

문자열의 수정이나 결합, 길이 관리가 필요하면 일반적으로 FString을 사용합니다.

FString characterName = TEXT("Ronnie");

UE_LOG(LogTemp, Log, TEXT("Name: %s"), *characterName);

위 코드의 *characterName은 일반 포인터에 역참조 연산자를 적용해 문자 하나를 얻는 동작과 다릅니다.

FString 클래스가 * 연산자를 오버로딩해 내부 문자열을 const TCHAR* 형태로 제공하도록 정의한 문법입니다.

표현식 의미
*characterPointer 일반 문자 포인터가 가리키는 문자 하나에 접근
*characterName FString의 연산자 오버로딩을 통해 const TCHAR*를 얻음

두 표현식은 기호가 같아도 타입에 따라 서로 다른 동작을 수행합니다.

언리얼 엔진의 문자열 타입을 사용하더라도 문자열이 문자 데이터의 연속으로 저장되고 끝을 구분해야 한다는 기본 개념은 이어집니다.


C++ Raw String Literal

C++에서 정식으로 Raw String Literal이라고 부르는 문법은 R"(…)" 형태입니다.

일반 문자열 리터럴에서는 역슬래시나 줄바꿈 등을 이스케이프 문자로 표현해야 합니다.

const char* path = "C:\\Game\\Data\\Character.txt";
const char* message = "첫 번째 줄\n두 번째 줄";

Raw String Literal을 사용하면 역슬래시와 줄바꿈을 입력한 형태에 가깝게 작성할 수 있습니다.

#include <iostream>

int main()
{
    const char* path = R"(C:\Game\Data\Character.txt)";

    const char* message = R"(첫 번째 줄
두 번째 줄)";

    std::cout << path << '\n';
    std::cout << message << '\n';
}

Raw String Literal도 결과적으로 null 문자로 끝나는 문자열 리터럴입니다.

C 스타일 문자열과 별개의 메모리 저장 방식을 제공하는 것이 아니라, 문자열 리터럴의 내용을 편리하게 작성할 수 있게 해주는 문법입니다.

용어 의미
C 스타일 문자열 null 문자로 끝나는 문자 배열
Raw String Literal 이스케이프 처리를 줄일 수 있는 R"(…)" 문법

std::string 사용하기

std::stringchar 기반 문자열의 메모리 할당과 복사, 길이 관리 등을 처리하는 표준 라이브러리 클래스입니다.

#include <iostream>
#include <string>

int main()
{
    std::string name = "Ronnie";

    name += " Jang";

    std::cout << name << '\n';
    std::cout << name.length() << '\n';
    std::cout << name.c_str() << '\n';
}

C 스타일 문자 배열을 직접 관리하는 것보다 문자열을 쉽게 복사하고 연결할 수 있습니다.

std::string firstName = "Ronnie";
std::string fullName = firstName + " Jang";

length() 또는 size()를 사용하면 문자열의 길이를 구할 수 있습니다.

std::cout << name.length() << '\n';
std::cout << name.size() << '\n';

c_str()을 사용하면 null 문자로 끝나는 const char*를 얻을 수 있습니다.

const char* cStyleString = name.c_str();

C 스타일 문자열을 요구하는 기존 C 함수나 외부 라이브러리와 연동할 때 사용할 수 있습니다.

c_str()로 얻은 포인터는 해당 std::string 객체가 소유한 문자 데이터에 접근합니다. 문자열의 내용을 변경하거나 객체의 수명이 끝나면 이전에 얻은 포인터가 더 이상 유효하지 않을 수 있으므로 장기간 저장하지 않는 것이 좋습니다.

실제 C++ 코드에서는 직접 new[]delete[]로 문자 배열을 관리하기보다 std::string을 사용하는 것이 일반적으로 안전하고 편리합니다.


정리

  • 문자열은 문자가 연속해서 저장된 데이터입니다.
  • 컴퓨터는 문자를 숫자로 저장하며, 문자와 숫자의 대응 규칙을 문자 인코딩이라고 합니다.
  • 문자 타입의 크기와 문자 인코딩은 같은 개념이 아닙니다.
  • 하나의 문자 리터럴은 작은따옴표로, 문자열 리터럴은 큰따옴표로 감쌉니다.
  • C 스타일 문자열은 마지막 null 문자 '\0'로 문자열의 끝을 구분합니다.
  • 문자열 리터럴 "Ronnie"에는 화면에 보이는 문자 6개와 마지막 null 문자가 저장됩니다.
  • 일반적인 문자열 리터럴은 const char 배열이며 대부분의 표현식에서 const char*로 변환됩니다.
  • 문자열 리터럴은 수정하면 안 되므로 const char*로 가리켜야 합니다.
  • 수정 가능한 문자열이 필요하면 문자열 리터럴로 char 배열을 초기화할 수 있습니다.
  • null 문자 없이 문자만 저장한 배열은 올바른 C 스타일 문자열이 아닙니다.
  • null 문자가 없는 배열을 C 스타일 문자열로 처리하면 정의되지 않은 동작이 발생할 수 있습니다.
  • sizeof는 실제 문자 배열 전체의 크기를 구하며 null 문자도 포함합니다.
  • std::strlen은 null 문자 앞까지의 문자 개수를 반환하며 null 문자는 길이에 포함하지 않습니다.
  • std::strlen에는 반드시 null 문자로 끝나는 올바른 문자열을 전달해야 합니다.
  • 동적으로 문자열을 복사할 때는 마지막 null 문자를 저장할 공간까지 할당해야 합니다.
  • new[]로 할당한 문자 배열은 delete[]로 해제해야 합니다.
  • 클래스가 동적 메모리를 직접 소유하면 복사 생성자와 복사 대입 연산자도 함께 고려해야 합니다.
  • strcpy_s는 목적지 배열 크기를 전달받아 문자열을 복사하지만 모든 컴파일러에서 동일하게 제공되는 것은 아닙니다.
  • wchar_t의 크기는 플랫폼에 따라 다를 수 있습니다.
  • wchar_t를 사용한다고 해서 문자 인코딩 문제가 자동으로 해결되는 것은 아닙니다.
  • 언리얼 엔진에서는 TCHARTEXT()를 사용해 엔진의 문자 타입에 맞는 문자열 리터럴을 표현합니다.
  • 언리얼 엔진에서 수정하거나 조합해야 하는 문자열에는 주로 FString을 사용합니다.
  • *FString은 일반적인 포인터 역참조가 아니라 연산자 오버로딩을 통해 const TCHAR*를 얻는 문법입니다.
  • C++ Raw String Literal은 R"(…)" 형태로 작성하며 이스케이프 처리를 줄여줍니다.
  • std::string은 문자 배열의 할당과 복사, 길이 관리를 대신 처리합니다.
  • std::string::c_str()을 사용하면 null 문자로 끝나는 const char*를 얻을 수 있습니다.
  • 실제 코드에서는 문자 배열을 직접 관리하기보다 std::string이나 언리얼 엔진의 FString을 사용하는 것이 일반적입니다.

이전 글: C++ 배열이란? 선언과 초기화부터 포인터와의 관계까지

다음 글: C++ 스택과 힙의 차이 알아보기: 메모리 구조와 동적 할당

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다