const char* msg = "Hello";
// 이 녀석은 지금 .rddata영역에 들어간 녀석이다.
// 수정이 불가하다.
SetMsg(const char* a)
{
a = "Bye";
}
// SetMSG 함수에 인자로 넘겨주어도 수정이 안된다.
const 가 안 붙어있다는 가정하에 값을 수정을 할려면
*a = "머시기"; 이런식으로 수정해야한다.
const char msg의 경우 const 가 이전에 붙어있어서
포인터 변수가 가르키는 곳의 데이터를 수정못한다!
msg의 문자열이 수정이 안되는 이유?
현재 Hello는 rodata영역에 '\n'까지 포함해서 있고
msg는 주소를 담고잇는 8바이트짜리 포인터 변수이다.
그래서Hello의 시작주소를 msg가 담고있는 것이다.
msg는 스택영역에 있는 포인터 변수이다.
지금 main함수의 스택은 이런식이고
SetMessage를 호출하면
Hello의 주소를 그대로 넘겨준 상황이다.
문자열이 수정이 불가능 한 이유로는
rodata영역에 들어가기 때문에 수정이 불가능하고 또한
const가 이전에 붙어있어서 주소로 접근하여 값을 수정하는 것이 불가능하다. (msg라는 포인터 변수의 데이터(가르키는 주소는 수정이 가능하다)
그리고 SetMessage함수에 msg의 주소(값을)를 const char a로 넘겨주고
a = "Bye"; 로 선언 및 초기화를 해주었을 경우
a는 const char* a 즉, a가 가르키는 값(주소)의 값(데이터 == Hello라는 문자열)수정이 불가능 한 것이지
a라는 포인터 변수가 담고있는 값부분(주소값)을 수정하는 게 불가능 한 것이 아니다.
따라서
SetMessage 함수가 호출되면
a라는 포인터 변수에 처음에
msg의 값에 담긴 "Hello"라는 문자열의 첫번째 주소값이 a에 담기기는 하지만,
a = "Bye"로 인해
데이터 영역에 있는 "Bye"의 첫번째 주소가 a라는 포인터 변수의 값에 할당된다.
그리고
a라는 포인터 변수는 스택메모리에 쌓인다.
SetMessage함수 호출이 종료되고 나면 a 포인터 변수 메모리 공간은 해제된다.
(함수 호출이 종료되면 사용할 수 없는 포인터 변수이다)
const char** pp;
를 처음에 해석을
(const char*)* pp;
포인터 변수인데 그 해석자료형을
const char* 로 보겠다라는 의미이다.
그러면 pp는 포인터 변수라서
(편의상 4바이트)
주소값 | 변수명 | 들고있는 값 |
---|---|---|
0x12121212 | pp | const char* 라고 보는 포인터 변수 |
지금 디버그를 보면은
ptr이라는 8바이트 포인터 변수를 보면은
주소값 | 변수명 | 들고있는 값 |
---|---|---|
0x000000cc9b6ffb98 | ptr | 0x000000cc9b6ffb74 (num이라는 변수의 주소를 가르킴) |
0x000000cc9b6ffbb8 | pp | 0x000000cc9b6ffb98 (ptr이라는 포인텨 변수의 주소를 가르킴) |
즉, 이중 포인터는 값으로 포인터 변수의 주소를 가르킨다.
int num = 100;
int* ptr = #
int* ptr2 = nullptr;
int** pp;
pp = &ptr;
**pp = 200;
cout << **pp << endl;
cout << num << endl;
cout << "pp의 주소(값) 변경" << endl;
*pp = ptr2;
cout << *pp << endl;
cout << **pp << endl;
지금 pp의 값을 nullptr로 변경하고나서 **pp로
값에 접근을 하게되면 에러가 난다.
이렇게 해주면 "Bye"가 뜨는것을 확인이 가능하다.
인자로 const char*& a 이런것도 가능함.
이렇게하면
인자로 념구준 msg = "Hello" 라는 녀석을 a라는 변수명으로 참조를 하겟다 인데
다시 a의 * 로 값에 접근
즉, msg의 값부분에 접근(Hello의 H의 주소에 접근) 하여
msg = Wow로 바꾸겠다 이다.
msg의 주소값은 똑같고 값부분의 데이터가 변경이됨.