BOX-IT/C++

C 포인터 개념을 소설로 쉽게 써서 정리한 글

Buang 2022. 3. 22. 20:31
반응형

양주종 강사님의 하단의 유뷰트 영상을 보면서 필기한 글임을 미리 알려드립니다.

https://www.youtube.com/watch?v=LtmJm068muw&list=PLlDAu2fzBjC6HjVmhYVlSMYSk4NAJiMnc&index=20 

 


c포인터 강의를 들으면서 필기를 하고 있는데

후반부에 정신을 차리고 보니 소설을 쓰면서 필기하고 있는 나 자신을 발견했다.

천생 문과생이 이과 과목 공부하면 이런 일도 생기는 거 같다.

 

도대체 어떻게 필기를 소설로 바꿀 수 있는지 궁금하다면

맨 하단을 보면 답이 나온다. 필기를 이런 식으로 할 수도 있다는 걸 나도 이번에 처음 알았다.

 

이렇게 소설 써서 올리면 분명 나중에 흑역사라면서 후회할 거 같기도 한데

C 포인터 개념이 어려우신 분들께 조금이나마 도움이 되었으면 해서 그냥 올려본다.

 

이 글은 포인터의 기초적인 개념이 무엇인지 설명하는 글이다.

한 번에 이해가 가지 않을 수 있다. 그게 원래 맞다.

 

포인터 개념 자체가 너무 어렵기로 유명하니 말이다.

나도 강의를 3번 돌려보고 나서야 이해했다.

그러니 처음에 포인터 내용을 보고 바로 이해가 가지 않았다고 해서

너무 좌절하거나 실망하진 않았으면 한다.

 

바로 이해가 안 간다면 '아. 난 보통 사람'이구나 하면 되는 거고

바로 이해가 간다면, '아, 난 천재구나'하면 된다.

 

 


1. 포인터 정의

 

point는 무언가를 지목한다는 의미다.

포인터(pointer)도 마찬가지다. 무언가를 지목할 때 쓰인다.

그렇다면 뭘 지목하는 걸까? 바로 주소다. 주소를 저장하는 변수가 바로 포인터다.

 

지금 이게 무슨 소리인가 싶을 거다.

 

하단의 추가적인 설명으로 넘어가보자.

미리 언급하자면 설명이 조금 길고, 왜 지금 이걸 설명하는 건지 싶을 거다.

그냥 한 번 읽어주면 왜 이렇게 길게 쓰는지 이해할 수 있다.

일단은 책을 가볍게 훑는다는 느낌으로 눈으로 읽어보길 추천한다.


2. 포인터 설명

 

int a = 20;
int* p =&a;

/*

a= 20
&a = 100번지
p = 100 번지
&p = 130번지
*p = 20

*/

 

 

 

첫 번째. int a = 20;

 

위에 작성된 코드를 보면 맨 첫 번째 줄에 int a =20; 이 보인다.

 

a라는 그릇에 20이라는 숫자가 담겨있다는 뜻이다.

int는 정수형을 뜻한다.

정수는 0과 양수(+1, +2, +3), 음수(-1, -2, -10)를 포함한 숫자를 의미한다.

 

20은, +20이기도 하다. 즉 20은 양수고

위에서 '정수 = 양수+음수+ 0'이라고 했으므로

20은 양수임과 동시에 정수이기도 하다.

 

int는 integer의 약자로 integer를 해석하면 정수다.

고로 20은 정수 즉 int가 맞다.

 

만약 int a = 24.5 처럼 실수를 넣으면 안된다

int는 정수만 담을 수 있는 그릇이라 실수는 담지 못한다.

아이스크림은 냉장고에 넣어둬어야지 햇 빛 잘 드는 베란다에 넣어두면 안되는 것처럼.


두 번째 &

 

int a = 20; 아래를 보면

int* p =&a;가 있다.

 

a&이 붙었다. &는 주소를 뜻한다.

&aa라는 그릇이 정확히 어디있는지, 그 주소를 가리킨다.

만약 a에 &이가 붙어있지 않았다면 a는 그냥 20이었을 것이다.

그런데 a 앞에 &가 붙음으로서 a의 값이 아닌 a가 위치한 장소를 나타낸다.

a가 만약에 100번지에 살고 있다고 한다면

&a = 100; 이 되는 거다.

 

정리하자면 이렇다.

 

a= 20;

&a =100;    <a가 위치한 주소. a는 100번지에 산다고 한다.

 

 

예시를 들어보자.

엄마가 나한테 씨리얼을 먹고 그릇을 어디에 뒀냐고 물었을 때

나는 내 방 책상 위에 뒀다고 말했다.

 

여기서 씨리얼 그릇이 a가 되고,

20이란 숫자는 씨리얼에 비유할 수 있으며

씨리얼 그릇이 있었던 장소인 내 방 책상은 &a가 된다.

 


세 번째 int* p =&a;

 

* 라고 못보던 녀석이 보인다.

* 아이의 이름은 '간접참조연산자'다.

이름이 참 어려운데 간접참조연산자를 비유를 통해 풀어서 쓰자면

 

'나는 가리키기만 했을 뿐인데, 값이 바껴버렸어.'

 

이다. 아직 잘 와닿지 않을 것이다. 아래 예시를 봐보자.

 

int a = 10;

 

int a = 10;은 a에 10이란 값을 넣어라!라는 걸 나타내는 것인데

a에 값을 담을 때 다르게 표현할 수도 있다.

 

*&a = 10;

 

이것 또한 a에 10을 넣어라! 라고 표현한 것이 된다.

&a는 a의 주소를 뜻한다고 했었다.

&a에 *가 붙으면 즉 *&a가 되면

 

'저는 지금 a의 주소(100번지)를 가리키고 있어요.

즉 a가 살고 있는 집의 주소를 알아낸 건데요,

a의 주소를 알아내서 a의 집으로 들어갔고,

a의 집에 있던 값을 이제 제 맘대로 바꿀 수 있어요.'가 된다.

 

*&a = 10;

 

을 정리해보자면

*&a는 a의 주소 100번지를 가리키고 있고,

a의 값을 마음대로 바꾸겠다고 선언한 것이다.

뭐로 바꾸겠냐고 물어봤더니

 

*&a 뒤에 =10;이 보인다.

즉 a의 값을 10으로 바꾸겠다고 한다.

근데 예초에 int a = 10;이였기 때문에 바꿨다고 하기도 뭐하지만 아무튼 그렇다.

 

 

여기서 깜짝 퀴즈 하나를 내보겠다.

 

*&a = 10 이었었다.

 

그렇다면 

 

*&a + 10은 뭐가 될까?

 

정답은

 

*&a + 10 = 20이 된다.

 

간접참조연산자 *를 설명하느라 딴 길로 가버렸는데

이제 다시 본론으로 돌아가보자.


 

int a = 20;
int* p =&a;

/*

a= 20
&a = 100번지
p = 100 번지
&p = 130번지
*p = 20

*/

위에서 int a = 20; 이 있었다.

여기서 int는 숫자(20)만 담는 그릇이었다면

int* p는 a라는 그릇의 주소(100번지)만 담는 것이다.

 

int* p= &a을 해석해보자면

a가 살고있는 곳의 주소를 p라는 그릇에 담아라고 말하는 거다.

a가 살고 있는 곳의 주소가 100(번지)라고 임의로 저장해뒀을 때

 

그럼 int* p = &a; 에서 p라는 그릇(변수)에는 100이 담길 것이다.

 

네 번째 &p

 

&p는 p의 주소를 물어보는 거다.

a의 주소는 100이라고 임의로 지정해뒀었다.

p의 주소는 130이라고 임의로 지정하겠다.

그럼 &p = 130이 된다.

 

다섯 번째 *p

 

위의 코드블럭을 보면 *p = 20이 있다.

여기서 *p는 뭘까? 위에서 int* p =&a;를 봤었다.

p는 여기서 a의 주소를 담고 있다고 이야기했었다.

 

즉 p가 가지고 있는 건 진짜 데이터가 아니라, 데이터의 번지수(주소)다.

p는 씨리얼을 가지고 있는 게 아니라 씨리얼 그릇이 놓인 장소가 적힌 주소종이만 가지고 있는 거다.

 

* 소설 시작 *

 

p는 씨리얼 그릇이 놓인 장소(주소)가 적힌 종이가 아닌 씨리얼(a가 가지고 있는 거)을 가지고 싶다.

하다못해 a가 가지고 있는 씨리얼을 공유해서 먹고 싶었다.

그래서 열심히 운동을 한다. 씨리얼을 찾으라 가는 길이 험난할 거 같아서 운동을 한거다.

그렇게 p*p로 각성했다.

운동을 열심히 한 *p는 본인이 가지고 있는 &a(a의 주소가 적힌 종이다. 100번지라고 적혀 있었다.)를 가지고

100번지에 찾아간다.

 

똑똑

 

a(씨리얼 그릇): 누구세요?

p: a씨네 집(100번지) 맞죠? 저는 p라고 해요. a씨가 가지고 있는 걸 가지러 왔어요.

a(씨리얼 그릇): 제가 가지고 있는 거요?

전 가지고 있는 게 씨리얼(20) 밖에 없어요.

이유> int a = 20; 을 통해서 a라는 그릇에 20을 넣어줬기 때문에 a20을 가지고 있다.

 

p: 그 씨리얼(20)이 바로 제가 가지고 싶었던 거에요.

 

a는 황당함에 입을 다물지 못했다.

갑자기 남의 집에 찾아온 것도 모자라

본인이 유일하게 가지고 있는 씨리얼(20)을 주라고 요구받는 입장에 처했으니 그럴 만도 했다.

 

p: 저한테 주는 게 내키지 않으신다면 씨리얼(20)을 공유해 주세요.

 

a는 어서 빨리 이 *p라는 아이와 떨어지고 싶어서 알겠다고 했다.

 

그리해서 *p는 씨리얼(20)a와 공유할 수 있게 됐다.

그런데 여기서 문제가 발생했는데, 바로 *p가 가지고 있는 너무 강한 특징이 문제였었다.

 

포인터 변수 *p의 특징

 

1) 포인터 변수가 가리키고 있는 곳의 값을 바꿀 수 있다.

 

열심히 운동해서 *p는 씨리얼(20)a와 공유하게 됐지만 *p는 씨리얼(20)이 금방 질려버렸다. 그래서 씨리얼(20)을 버리고, 초코파이(30)을 데려왔다.

 

이제 *p*p = 20;이 아니었다.

* p = 30; 이 된 것이다.

 

이렇게 되면 a한테 변화가 생긴다.

a는 원래 씨리얼(20)을 가지고 있었는데 a가 가지고 있던 게 씨리얼(20)에서 초코파이(30)으로 변하면서 덩달아 a도 씨리얼(20)을 버리고 초코파이(30)를 가지고 있는 것으로 변해버린다.

 

어째서냐고 묻는다면 *p라는 포인터 변수의 기능 중에 본인이 가리키고 있는 곳의 값을 변화시킬 수 있는 능력이 있기 때문이다. *pa를 가리키고 있고, a20이란 값을 가지고 있었다. 20이란 값을 *p는 변화시킬 수 있는 능력을 가지고 있는 것이다.

 

a 입장에선 황당할지도 모른다. 본인이 가지고 있는 씨리얼(20)을 공유해줬을 뿐인데 갑자기 *p가 씨리얼(20)을 버리고 초코파이(30)을 택했다는 이유 하나만으로 본인의 의사와는 상관없이

 

int a =20;

에서

int a = 30;

으로 변해야 했으니 말이다.

 

 

 

 

 

 
반응형