프로그래밍 공부
작성일
2024. 1. 12. 17:22
작성자
WDmil
728x90

2.1.2 문자열 리터럴

 

C++ 프로그램에서는 (사실 거의 모든 프로그램) 따옴표로 둘러싼 문자열을 흔히 볼 수 있다.

 

예를들어 문자열 hello를 출력한다고 했을 때

cout << "hello" << endl;

여기서는 hello라는 변수를 참조하여 그 값을 내보내지 않는다.

 

위 코드에서 hello를 문자열 리터럴 이라고부른다. 이렇게 코드 구문 자체가 변수가 아닌 값을 나타낼 때 문자열 리터럴 이라고 한다.

 

문자열 리터럴을 변수에 대입할 수도 있지만, 위험할 수 있다.

 

문자열 리터럴은 읽기 전용 메모리에 할당되기 떄문이다.

 

이런 이유는 컴파일러가 메모리를 절약할 수 있게 하기 위함이다.

 

예를들어, 코드에서 hello를 수백번 사용 하더라도, 단 하나의 hello만 메모리를 할당 받고, 나머지는 해당 영역을 참조하는 형태로 이루어진다.

 

이러한 방식을 리터럴 풀링(literal pooling) 이라고 한다.


문자열 리터럴은 변수에 대입될 수 있다.

 

하지만, 문자열은 읽기 전용 메모리에 위치하기 때문에 리터럴 풀링이 적용되어 있을 가능성이 높다.

따라서 변수에 대입되는것 은 위험할 수 있다.

 

C++에서는 공식적으로 문자열 리터럴을 크기n의 const char 배열 타입이라고 부른다.

 

하지만, const 개념이 없는 환경에서 작성된 코드와의 하위 호환성 떄문에 컴파일러 대부분이 이를 강제하지는 않는다.

 

그래서 문자열 리터럴을 변수에 대입할 때는 const char*타입 대신 char* 타입 변수를 이용할 수 있다.

이렇게 하더라도 대입한 문자열을 변경하려고 들지 않는 이상, 문제없이 사용은 가능하다.

 

일반적으로 문자열 리터럴을 변경할 때 어떤일이 일어날 지는 정의되어 있지 않는데, 그 이유는 사용한 컴파일러에 종속적이기 때문이다. ( 컴파일러에 따라 다르기 때문 )

 

예를들면 다음과 같은 상황을 볼 수 있다.

char* ptr = "hello";
ptr[1] = 'a'; // a는 정의되지 않은 동작이다. 뭔일이 날지 알 수 없다.

 

그래서 문자열 리터럴을 변수로 사용할 때 에는 const 변수를 이용하는 것이 훨 안전하다.

 

const char* ptr = "hello";
ptr[1] = 'a'; // 컴파일 에러! 읽기 전용 메모리에 쓰기 시도

위와같이 사용하면, 컴파일러에 의해 오류가 나타나서, 알아보기 쉽다.


그래도 쓰고싶다면,

문자열 리터럴은 문자 배열 (char[])의 초깃값 으로 이용할 수 있다.

 

이경우 컴파일러가 자동으로 해당 배열의 크기를 문자열과 널 마크를 복제해서 담을 수 있을 만큼 할당해준다.

그리고, 해당 배열을 읽기 전용 메모리에 두거나 리터럴 풀링에 포함하지 않는다.

char arr[] = "hello"; // 컴파일러가 자동으로 문자열 배열 크기에 맞게 메모리 할당
arr[1] = 'a'; // 배열 내용 수정이 가능하다.!

 

728x90