2010. 4. 2. 15:05

문자열에 대한 레퍼런스는 어떻게 해야 할까?


보통 int형이나 float형등에 대한 레퍼런스는 쉽게 쓸 수 있습니다.

다음 예제를 살펴 봅시다.

wchar_t *abc = L"가나다라마바사";

wchar_t *abc2 = new wchar_t[256];

wchar_t abc3[256];

통상적으로 위와 같은 형태로 많이 사용합니다.

이때, 이 변수들에 대한 레퍼런스(문자열에 대한 레퍼런스)는 어떻게 할 수 있을까요?

물론, wchar_t &def = abc; 과 같은 형태는 불가능합니다.


문자열에 대한 레퍼런스를 할 수 있는 방법은 할당된 메모리 영역에 따라 두가지가 있습니다...

1) 스택 영역(Stack Segment)과 초기화되지 않은 데이터 영역(Uninitialized Data Segment)

아래는 스택 영역에 할당된 변수의 선언입니다.

int main(void)
{

    char string_1 = 'a';

    char &ref_str = string_1;

    return 0;

}

위에서 보시는 string_1은 char형이 1 byte기 때문에 레퍼런스를 string_1에 붙여줄 수 있습니다.

그 이유야 두말할 필요없이 'a'가 1 byte기 때문에 레퍼런스 선언이 가능합니다.

왜냐하면, 레퍼런스도 1 byte char형이기 때문이죠.

하지만, 다음 문법을 보겠습니다.

int main(void)
{

    char string[20] = "Hello World!!";

    char ???

}

위에서 선언된 string은 배열입니다. 좀 더 정확하게 말하자면, 배열은 포인터 상수입니다.

여기서 포인터의 상수란, 그 크기가 유동적인 것이 아니라 컴파일 타임에 정해졌다는 것을 의미합니다.

다시 말하면, 이미 string이라는 포인터가 가리키는 위치는 스택 영역 어딘가에 20byte로 할당된 메모리

상이라는 말인데, 여기서 중요한 점은 string이 가리키는 곳을 절대 바꿀 수 없다는 것이 포인터 상수의

특징입니다.

문제의 핵심은 컴파일러가 제공해주는 자료형이 char, short, int, long, float, double 등등..

문자열 상수 20 byte 모두 참조할 수 있는 자료형이 존재하지 않는다는 것이 핵심입니다.

그렇기 때문에, 결론은 20 byte 크기를 참조할 수 있는 사용자 정의 자료형을 사용하여야 한다는

것입니다.

아래가 스택 영역에 할당된 문자열 상수를 레퍼런스로 선언할 수 있는 해답입니다.

#include <iostream>

using std::cout;
using std::endl; 

struct String
{
    char str[20];
};

int main(void)
{

    String string;

    strcpy( string.str, "Hello World!" );

    String &ref_str = string;

    cout << ref_str.str << endl;

    return 0;
}

 

2) 초기화된 데이터 영역(Initialized Data Segment)

아마 위의 방법을 보시고 어딘가 좀 못마땅하고 문법적으로도 까다롭다는 것을 느끼실 겁니다...

하지만 초기화된 데이터 영역에 할당된 문자열을 레퍼런스로 선언/정의하는건 간단합니다..

해결책은 아래와 같습니다.

 

#include <iostream>

using std::cout;
using std::endl;

int main(void)
{

    char *string = "Hello World!";

    char *&ref_str = string;

    cout << ref_str << endl;

    return 0;

}

이것에 따른 의문도 있을거라고 생각되니 정리해 드리겠습니다.

char *string;에서 char *도 하나의 자료형입니다. "문자 포인터형"이지요..

마찬가지로 "문자 포인터형"의 레퍼런스를 하나 선언하여 string으로 초기화한다면 문제없습니다.

char *(&ref_str) = string;

※ 하지만 , 위에서 선언된 레퍼런스로 접근은 읽기는 가능하나 쓰기는 불가능합니다.

    왜냐하면, string이 가리키는 곳은 초기화된 데이터 영역에 할당된 문자열 상수이기 때문입니다.

    Initialized Data Segment는 오직 읽기만 가능하며, 쓰기는 불가능합니다.

    이 영역의 메모리 해제는 프로그램이 종료될 때, 해제가 됩니다.


Written By Sim-Hyeon, Choe