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")이다.
'컴퓨터 수업 > C++' 카테고리의 다른 글
재귀에 대한 생각. (0) | 2020.11.04 |
---|---|
Outer, Inner Class의 생성자와 소멸자 호출 타이밍 (0) | 2020.11.04 |
How will we deal with "Past-happened" problem (0) | 2020.11.04 |
기본생성자(void) 호출방법. (0) | 2020.10.31 |
-> operator는 역참조 연산자인가? (0) | 2020.10.27 |