프로그래밍

나도 공부하고 너도 공부하는 C/C++ (5)-1

휴... 오늘은 조금 시간이 남아서 써보겠습니다.

5장은 포인터인데, 사실 C와 C++을 처음 배우는 입문자들이 가장 어려워하는 개념이 포인터 개념일 거십니다..

포인터 개념이 어려운 이유는 사실 여러 가지 개념이 합쳐져 있는 개념이라 그래요.

천천히 하나씩 풀어나가 보겠읍니다.

 

 

5. 포인터(Pointer, *)

(1) 주소값(Address)

기본적으로 메모리 공간을 우리가 사용하기 위해서는

a) 메모리 공간에서 어떤 공간이 현재 사용할 수 있는 공간인지

b) 그 공간 중에서 어떤 공간을 이용할 것인지

c) 사용한 후 어떻게 사용 중임을 나타낼 것인지

의 3가지가 필요해.

 

a)의 경우, 만약 메모리에 정보가 있음에도 불구하고 모든 공간을 사용할 수 있는 공간이라고 생각하고 사용해버리면 문제가 될거야.

정말 중요한 정보가 저장되어 있는 공간의 정보를 덮어씌워 버릴 수 있으니까.

 

b)의 경우, 메모리 공간은 항상 연속적으로 사용되는 것이 아니야.

왜냐면 메모리 공간이 모두 동시에 사용되거나 동시에 사용을 중단해서 빈 공간이 되는게 아니거든.

때로는 어떤 공간 A는 10초동안 사용되었고, 어떤 공간 B는 20초동안 사용되었다면

10초동안은 공간 A가 비어있는 상태가 되는 거지.

(엄격한 기준으로 본다면 실제로 메모리 공간 내의 데이터가 아예 비워지는 것은 아니고,

그저 "사용할 수 있음" 처리가 되는 것이지만 이는 현재 우리 수준에서 크게 중요치 않아)

그러므로 비어있는 공간들 중에서 어떤 공간을 사용하는 것이 이상적일 것인지에 대한 문제야.

 

예를 들면, 예를 들어 메모리 공간이 0번부터 9번까지 있는데, 메모리 공간의 사용 상태가 이렇다고 해보자.

 

0123456789

1100000100

(1이 사용 중, 0이 미사용 중)

 

이럴 때, 내가 사용하고자 하는 데이터의 크기가 2칸을 차지한다고 하면

 

0123456789

1111000100

1101100100

1100110100

1100011100

1100000111

 

위와 같이 5가지의 방법으로 저장공간을 사용할 수 있겠지?

다음에 사용될 데이터의 크기가 얼마인지 모른다고 가정했을 때에는 가장 마지막의 1100000111로,

8번과 9번에 데이터를 저장하는게 가장 나은 상황이라고 생각할 수 있어.

 

그런 것들은 우리가 처리하는 레벨은 아니지만, OS가 이러한 메모리 관리도 담당하고 있으니

아 OS가 저런 것들을 해주는구나 정도로 알고 있으면 될 거 같다.

 

c)의 경우, 메모리 공간을 사용했으면 사용했다고 표시를 해두어야 a)의 문제도 막을 수 있겠지.

 

여튼 이런 식으로 메모리 공간을 사용하기 위해서는 위와 같은 3가지가 필요해.

그래서 그 3가지를 한 번에 관리 및 처리하기 위한 방법으로

메모리 공간마다 위치값인 "주소"를 부여하고

그 주소가 사용되고 있는지 혹은 사용되고 있지 않은 지를 구분하는 방법을 사용하기로 한거야.

(이 역시 OS가 처리하는 부분)

즉, 메모리 공간에는 주소라고 하는 값들이 각 공간마다 부여되어 있다는 것이지.

(그 공간 하나 당의 물리적인 크기는 OS가 나누고 있으므로 우리는 신경쓰지 않아도 된다)

 

그러므로 메모리 공간에 저장되어 있는 특정 데이터에 직접적인 접근을 하기 위해서는

그 데이터가 위치하고 있는 주소값이 필요해.

 

(2) Call by Value, Call by Address, Call by Reference

C 언어는 일반적인 변수를 선언하게 되면 모두 새로운 주소값이 부여되는 개별 변수로 만들어줘.

그리고 그 변수에는 부여된 주소값과, 주소값 내부에 있는 데이터의 해석까지 포함되지.

 

그런데 그 변수를 사용하면, 그 변수의 주소값이나 이런 것들을 가져오는 것이 아니라

그 변수가 가지고 있는 주소값에 있는 데이터를 가져온다는 것을 이해하는 것이 가장 어려운 부분일거야.

 

예를 들어 보자.

 

int a = 10;(a의 주소 : 0F000000이라고 치자)

int b = a;(b의 주소 : 0F000004이라고 치자)

 

이 두 식을 보자면,

a라는 이름의 변수에는 실제로 변수 a에 해당하는 데이터가 저장되어 있는 주소값인 0F000000과 그 위치에 저장되어 있는 데이터가

정수 값이라는 정보가 담겨있어.

하지만 두 번째 줄의 int b = a; 처럼 사용하게 되면

a가 가진 위치에 해당하는 데이터만 가져오게 되는 거야.

그 데이터가 어디 있는지는 알바 없는거지.

그래서 변수 b는 a와는 별개로 새로운 주소값 0F000004라는 주소를 부여받았고, 그 내부에는 a에서 가져온 10만 저장되는 셈이야.

 

즉,

a(주소 0F000000, 실제 데이터 10)

b(주소 0F000004, 실제 데이터 10)

이렇게 저장되어 있는 거지.

 

여기서 a의 데이터를 변경해보자.

 

a = 5;

 

이렇게 되면, 변수 a가 가진 주소의 실제 데이터를 5로 바꾸는 거야.

그러니 b는 a와 똑같은 몸이 아니라, a가 가진 값만 가져온거니까, b는 a의 값이 5로 변한 것과는 별개로 남게되는거지.

 

a(주소 0F000000, 실제 데이터 5)

b(주소 0F000004, 실제 데이터 10)

 

이렇게.

 

언뜻보기에는

int b = a;

라는 문장이

b와 a는 하나의 같은 몸이 된다고 해석하기 쉬울 수 있는데,

그게 전혀 아니라는 점을 꼭 기억해.

 

이런 것을 두고 call by value 방식이라고 해.

우리가 프로그래밍에서 어떤 변수를 부르거나 함수를 불러서 이용하는 행위를 두고 "call 한다" 혹은 "call" 이라고 부르거든?

즉, 부르기는 불렀는데 뭘 부르냐면 값만 부른다는 거야.

위의 방식에서도 int b = a;라고 했지만, b와 a를 한 몸으로 만든 거였어? 아니지.

b가 가진 저장 공간 안에 a가 가진 10이라는 "값(value)"을 저장한거야.

 

call by value 방식으로 b까지 변하게 하고 싶다면,

int a = 10;

int b = a;

b = a = 10;

이런 식으로 a가 변할 때 b도 변하게 해주면 돼.

그런데.. 엄청 불편하잖아.

 

그래서 다른 방법이 바로 "주소값"을 이용하는 거야.

변수의 데이터 값을 특정한 메모리의 주소값으로 저장하고,

그 데이터를 부를 때 그 주소값을 통해 해당 메모리가 위치한 실제 위치로 이동할 수 있다면

그 데이터 값에 직접적으로 액션을 취할 수 있을 거야.

그러므로 부르기는 부르되(Call), 단순히 값만을 불러오는 것이 아니라,

그 값이 위치하고 있는 실제 주소 위치에 접근하여 를 불러온다 하여

Call by Address라고 부르지.

 

자 아까 위에서 보자.

 

int a = 10(a의 주소 : 0F000000);

int* b = &a(b의 주소 : 0F000004);

 

이렇게 선언하고 이용하는 것이 Call by address이자, 우리가 설정한 5장의 주제인 "포인터"를 이용한 것인데

이용하는 방법에 대해서는 (5)-2에서 설명할게.

 

여튼 내용을 보면

 

a(주소 0F000000, 실제 데이터 10)

b(주소 0F000004, 실제 데이터 0F000000)

 

이렇게 저장이 되어 있는거야.

그래서 b는 데이터를 보려고 하면 a의 주소값을 출력하게 돼.

 

그래서 a = 5로 바꾸게 되면

 

a(주소 0F000000, 실제 데이터 5)

b(주소 0F000004, 실제 데이터 0F000000)

 

로, 변하게 되지.

 

b는 주소값을 가지고 있는 변수기 때문에 그 해당 주소값으로 "직접 접근"하기 위해서는

그냥 b라고 하면 안되고 앞에 *을 붙여서 써.

*을 붙인다는 의미는 쉽게 말해 그 해당 변수가 가진 데이터의 값을 주소로하는 메모리 위치에 접근해서 데이터를 가져온다고 생각하면 돼.

 

그래서

printf("%d", *b);

라고 하면

b가 가진 주소값인 0F000000의 위치에 있는 데이터인 5를 가져와서 출력하게 되므로,

 

출력 : 5

라는 결과를 얻게될거야.

 

어때, a만 바꿨음에도 b가 출력하는 값까지 바뀌었지?

주소값을 이용해서 데이터에 접근하는 방식으로 하면, 변수에 직접적으로 접근할 수 있어.

 

그럼 call by reference는 무엇일까?

저번 장에서 밑에 댓글로 누가 언급했었던 내용이야.

함수에 입력값을 넣을 때 그냥 변수를 넣게되면 그 값을 복사해서 함수 내부에서 새로운 변수를 선언한다고 했었지.

그래서 입력값을 변경하더라도 실제로 그 입력값의 원래 변수는 변하지 않아.

 

void function(int a){

a = 10;

}

 

void main(){

int value = 1;

function(value);

}

 

이렇게 작성을 하더라도, value는 function함수에서 10으로 바뀐거 같아 보이지만 int a는 value 그 자체가 아니라

단순히 value의 값이 복사된 새로운 변수일 뿐이야.

그래서 value는 여전히 1인거지.

이렇게 함수에서 입력값의 데이터를 복사하는게 아니라, 직접적으로 접근하고 싶을 때

사용하는 방법이 call by reference(참조에 의한 호출)이야.

 

사용방법은 매우 간단해.

입력값 중 실제로 데이터를 변경하고 싶은 입력값 앞에 "&"을 붙여주면 돼.

위의 예시로 보면

 

void function(int& a){

a = 10;

}

 

void main(){

int value = 1;

function(value);

}

 

이렇게.

function함수 옆 입력값에 &이 붙은 걸 볼 수 있지?

저렇게 하면 함수가 실행된 이후 value 값은 10으로 변경 돼.

call by reference는 일반적으로 함수의 단위에서 실행되니까 잊지마.

 

여튼..

그럼 왜 call by value와 call by address, call by reference로 변수와 데이터 공간을 접근하는 방법을 나눌까?

여러 이유가 있겠지만 상황에 따라 다르게 사용하는 상황이 필요하기 때문이야.

메모리를 접근할 때 직접 접근해서 바꿀 수 있는 상황이어야 할 때도 있지만,

때로는 메모리의 접근하더라도 그 데이터를 바꾸거나 건드리면 안되는 상황이 필요하다면

굳이 call by reference 또는 call by address로 사용해서 위험을 자초하느니, call by value로 그냥 변수 선언해서 위험도를 낮추는게 좋을 때도 있는거지.

물론 이거 외에도 이유는 많지만

초보자가 아직 그거의 원인까지 파고 들어서 공부할 필요는 없으니까...

 

 

 

다음 번에는 진짜 포인터를 사용하는 방법에 대해서 논의해보도록 하겠읍니다.

피드백은 감사합니다

 

5개의 댓글

2019.12.13

좋은글이네요 ㅎㅎ

0

:)

0
2019.12.13

더블포인터를 내놓으시오

0
2019.12.14

C++ 가르친다는 새끼가 reference 소개도 똑바로 못하니 ㅋㅋ

0
2019.12.14
@강간범

틀린 내용을 가르쳐 주는 건 좋은데

말은 싸가지 있게 해주었으면 좋겠네

내가 다 알고 가르친다고 한 적도 없거니와

제목에서 분명히 "나도 공부하고"를 첨가하여 나도 좆도 모릅니다라는 걸 강조했는데;

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜 조회 수
180459 [잡담] 드디어 왔다 레이니 1 ltearl 0 7 시간 전 131
180458 [프로그래밍] 그 혹시 게임쪽 종사자 있음? 12 god79ii 0 7 시간 전 187
180457 [컴퓨터] sata 케이블때문에 ssd가 망가질 수도 있나요? 8 드웨인토마스 0 9 시간 전 170
180456 [컴퓨터] 구글에서만 검색창 방향키가 안먹음 뒷북 0 12 시간 전 66
180455 [모바일] 횽들 어거좀 봐줘 6 부자가될개붕이놈들 0 13 시간 전 139
180454 [컴퓨터] 선생님들 혜안을 구합니다 9 빠른인정빌런 0 14 시간 전 134
180453 [모바일] 당근으로 갤럭시탭 s9 울트라 사기로했는데 2 말이야방구야 1 14 시간 전 221
180452 [모바일] 갤럭시 동영상 자르기 안되는 이유 아시는분?? 3 일토준지 0 14 시간 전 111
180451 [프로그래밍] 코린이 ㅅㅂ 뭐가 문젠지 모르겠어요 2 집에가게해줘 0 15 시간 전 220
180450 [컴퓨터] 해피해킹 키보드 회사서 못 쓰는 이유 3 닉네임변경후13일차 0 16 시간 전 279
180449 [컴퓨터] 컴 바꿧듬 10 탑똥 1 16 시간 전 128
180448 [컴퓨터] CPU 불량이 맞는가!? 14 꺄꺄룽 0 16 시간 전 174
180447 [정보] 최근에 꽤 핫했던 레노버 y700 2세대 정보 모음입니다. 13 SeraMint 2 16 시간 전 201
180446 [잡담] 님들 컴터 조립할 때 ㅈ같았던 경험들 있음? 4 UBCS 0 17 시간 전 128
180445 [컴퓨터] LG OLED티비쓰는데 HDMI로 컴연결해서 쓰거든 11 뚱땡보 0 17 시간 전 116
180444 [잡담] DDR5 삼성 시금치램에 방열판 달고싶은데 10 내일까지 0 18 시간 전 136
180443 [컴퓨터] 3.5mm 헤드셋을 연결했는데 마이크에서 스피커소리가 나옴..... 12 아건 0 19 시간 전 103
180442 [컴퓨터] 모니터 화이트스크린 심심할땐개드립 0 20 시간 전 45
180441 [모바일] 유튜브 뮤직 왜 안되는지 아는 사람?? 8 티탄즈 0 20 시간 전 144
180440 [컴퓨터] 10년된 컴터 이제 보내주려하는데 이거 살만한가여? 12 응가쌀땐폰필수 0 21 시간 전 177