C언어는 다른 언어보다 C배 어렵다고 합니다.
그 이유로 포인터를 이야기하죠.
자바,파이썬 등의 대중적인 언어와 다르게
메모리참조를 직접 할 수 있는 기능이 있고
이 기능 때문에 개발자들의 머리가 박살이 납니다.
그와 관련으로 중요한 개념 중 하나가
Call by value와 Call by reference입니다.
여러분들이 구글링으로 "CS면접답변"이라고 치면 나오는 것 중 하나로
"값 복사 vs 주소값 참조"이런 이야기도 있고
"포인터를 건드냐 안건드냐 차이다"이런 말도 있죠.
이걸 암기한다면 복잡하겠지만
원리를 알고보면 당연한 이야기입니다.
컴퓨터관련 전공하신 분들이라면
이 그림은 한번쯤 보셨을 겁니다.
우리가 작성한 프로그램 함수는
stack영역에서 실행이 됩니다.
가장 필수적인 main함수부터
여러분들이 작성한 다양한 함수까지
모두 stack에서 호출되어서 동작합니다.
void ex(){
ex();
}
int main(){
ex();
}
이런 프로그램을 실행하면 계속 동작하다가
'stack overflow'라는 에러메시지가 나옵니다.
ex라는 함수가 종료되지 않고 계속 실행되니
stack이 넘치게 되면서 발생하는 에러죠.
이렇듯 함수를 수행할 때 이렇게 stack에서 동작하는 것.
알아두고 갑니다.
프로그램은 다음과 같다고 가정합니다.
void swap(int a,b){
int tmp=b;
b=a;
a=tmp;
}
int main(){
int a=1;
int b=2;
swap(a,b);
printf("%d %d\n",a,b);
return 0;
}
어떤 값이 출력이 될까요??
만약 2,1 이렇게 출력이 된다고 생각하셨다면
위의 그림을 보면서 다시 보겠습니다.
먼저 main을 stack에 동작시키고
main함수 안의 a와 b를 stack에 저장합니다.
그 후에 swap을 호출합니다.
swap도 인자로 받은 a와 b가 있습니다.
swap의 a와 b는 swap의 주소값 근처에 있습니다.
만약 swap함수가 종료가 되면
swap함수에 저장된 a,b도 사라지게 됩니다.
그리고 다시 main으로 돌아와 printf를 실행합니다.
printf안의 a와 b는 main에서 선언한 a b로
값이 1,2입니다.
그러니 1,2로 출력이 될 것입니다.
그럼 어떻게하면 우리가 생각한데로
값이 바뀌게 만들까?
swap함수를 다음과 같이 수정해보겠습니다.
void swap(int *a,int *b){
int tmp=*b;
*b=*a;
*a=tmp;
}
이렇게 call by reference를 활용하면 됩니다.
아까와 다르게, 인자값을 int 포인터로 받아서
a,b의 주소값이 넘겨졌다는 걸 알 수 있습니다.
이제 swap함수가 실행이 될 때
main에 선언된 a와 b의 주소값이 들어갑니다.
swap에서는 a,b의 주소값을 참조해 값을 변경합니다.
이후에 swap함수가 종료가 되고 main으로 오면
swap의 stack이 날라가더라도
이미 swap에서 main에 선언한 a,b의 주소값을 통해 값을 바뀌었기 때문에
우리가 원하는데로 값이 바뀌는 결과를 볼 수 있습니다.
CS를 단순히 면접용으로만 공부했을때는 잘 몰랐지만
최근 OS공부를 진행해보면서 필요성을 느끼기 시작했습니다.
실제메모리주소-가상메모리주소와 매칭을 하는 개념을 공부하면서
가상화 등 OS관련으로 뭘 할려면
메모리 참조를 제대로 알아야되겠다 생각이 들었습니다.
그냥 무미건조하게
"값복사 vs 주소참조"라고 외우기보다는
메모리관점에서 어떻게 확장할 수 있을지 정리를 해본다면
이해할 수 있는 폭이 넓어질 것입니다.
메모리와 명령어의 상호작용, 왜 알아야할까?? (1) | 2023.10.10 |
---|---|
2진수계산,왜 알아야하고 어떻게 사용할까?? (1) | 2023.10.08 |
레지스터, 왜 알아야하고 어떻게 동작할까? (0) | 2023.10.05 |
(어그로 아님) int자료형은 언제나 4바이트가 아니다 (0) | 2023.09.24 |
for와 while문, 왜 반복문은 2개가 있을까??(C언어 고찰) (2) | 2023.09.23 |
댓글 영역