문자열 관리 {char*, char[] , string}

2020. 11. 4. 12:00컴퓨터 수업/C++

C++에서 문자열을 관리하는 방법

char* , char[], string


각 방법들이 문자열을 어떤 방식의 메모리 관리로 운용하는지

char[] str1 = "STR1";
char*  str2 = "STR2"; // 실은 동작하지 않는다.
string str3 = "STR3";

1. char[]

2. char*

3. string은 잘 모른다... ㅠ

 

정리:

 

우선 Hello라는 상수 문자열 형태가 "실제론" 어떤 값을 갖고 있는지 고민 해 볼 필요가 있는데,

우리는 char라는 엔터티에 문자열을 저장할 수 없으므로, 문자열을 "주소"로 다룬다.

따라서 상수 문자열 형태도 "실제론" 메모리주소를 나타낸다.

따라서, char* str2 = "Hello"의 경우엔 str2에 상수문자열 형태의 Hello란 문자열의 첫 글자, H의 offset memory address가 저장된다. 이 경우에 msvc에선 컴파일되지 않는데, 이는 아래서 다루겠다.

char str1[] = "Hello"의 경우엔, str1이 배열 포인터(정적 포인터) 형태로 선언되었으므로, 그 그 길이가 초기화와 동시에 이루어져야 한다. (런타임에 결정할 수 없음.)

 

이 두 차이는 정적포인터와 비정적포인터의 차이에 대한 이해기도 하고, 배열포인터와 비정적포인터의 차이에 대한 이해기도 하다.

 

단적인 예시로 말하자면 두 포인터는 거의 혼용되어 쓰이지만 다음과 같은 statement에서 차이가 난다.

str1(배열 포인터, 정적 포인터)의 경우엔,

*(str1+2) = *(&str1+2) = 'R' 로 같다.

str2(비정적포인터)의 경우엔,

*(str2+2) = 'R'

*(&str2 +2) = nullptr;

로 다르다.

 

이런 점에서 하나의 이해를 더 하자면, 정적포인터 or 배열포인터의 경우엔 포인터변수 그 자체의 값이

그 포인터변수의 주소 (이중포인터변수) 와 같다는것이다.

위의 1006 번지 메모리 주소에, 1006번지가 적혀있는것을 보면 이해할 수 있다.  뭔가 호칭하는 바가 있을 것 같은데... 재귀포인터? ㅠ


왜 문자열이 난해한지, 컴파일러의 종류에 따라 다루는 방식.

각 상황에 맞게 적절한것을 사용하는 것이 가장 바람직한 방법일 것이다. 그리고 문자열은 다루는 바가 조금은 난해하기 때문에, 각 컴파일러(IDE)에서 다루는 방식이 조금씩 다르다, (DevC++)minGW(gcc)와 (VS)msvc로 나눠서 설명하자면, (심지어 C++ 버전에 따라 다르다.)

 

첫번째 문제)

Visual Stuido에서 다음과 같은 statement는 컴파일 불가하다.

(참고로 gcc 컴파일러에선 잘 된다.)

위에서 얘기했듯이, "Hello"는 정적포인터변수이다. 따라서 const char* 이고 str2는 내가 char* 로 선언했으니, 엔터티가 다르다는 것은 이해할 수 있다. 이는

 

char* str2 = (char*)"Hello"

 

로 해결한다.


두 번째 문제) 정적문자열을 수정해야 하는 경우, char[]를 수정해야 하는 경우.

 

예를들어, 내가 char를 80개까지만 받고 싶다면, char str[80]이라고 선언했을 것이다.

 

위에서 char str[] = "Hello" 는 가능했다, 왜냐면 (배열 포인터는 컴파일 타임에 길이가 결정되어야 하므로) 이런 점을 지키는 위와 같은 statement는 가능했다.

 

하지만 다음과 같은 코드는 컴파일되지 않는다.

str은 정적포인터변수이므로 수정할 수 없다. 따라서 지금은 이미 고정되어 버린 str를 수정하기 위해서,

str의 메모리 주소에 다른 상수문자열의 주소를 복사대입 해주는것이 아니라,

str의 메모리 주소에 다른 상수문자열의 값을 복사대입 해주어야 한다.

이때 사용하는것이 strcpy(str,"Hello")이다.