포인터 뿌셔보기
포인터에 대해 집중 탐구를 해봐염.
포인터가 뭐임?
*
는 포인터 선언으로 해당 변수의 메모리 주소값을 참조하는 용도로 사용할 수 있다. 그 후 변수의 메모리 주소값을 얻고 싶을 땐 &
연산자를 사용한다. 그러고 메모리 주소에 있는 실제 값을 가져오거나 변경하고 싶으면 다시 *
를 써서 역참조 용도로 사용한다.
포인터가 왜 필요한데?
애초에 우리가 코드를 작성할 때 변수를 선언하고 사용하면 그게 다 어디에 저장되는가? 메모리에 저장된다. 더 자세한건 여기서
그래서 그 값의 메모리 주소값을 사용하고 싶을 때는 포인터(*)와 주소 연산자(&)를 사용하는거다.
포인터를 사용하는 경우는 주로
- 변수간의 값을 서로 바꿔야 될 때나,
- 연결리스트를 구현해야 될 때 등 다양한 용도에서 쓰인다.
코드로 살펴보자
말로 하면 이해 되는 것 같은데 막상 코드를 보면 아니다.
고로 예제 코드를 몇 가지 봐보자.
먼저 변수 서로간의 값을 바꿀 때는 아래처럼 swap 함수를 만들 수 있다.
swap()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
void swap(int* p, int* q);
int main(void) {
int a = 4;
int b = 5;
swap(&a, &b);
printf("A: %d, B: %d", a, b);
return 0;
}
void swap(int* p, int* q) {
int temp = *p; // temp에 p가 가리키는 값을 저장 (주소가 아님)
*p = *q; // p가 가리키는 위치에 q가 가리키는 값을 저장
*q = temp; // q가 가리키는 위치에 temp 값을 저장
}
근데 왜 굳이 포인터를 사용한 함수를 만들어서 쓰는걸까? 이에는 크게 2가지 이유가 있다.
- 여러번 사용할 수 있으니까.
만약 값을 한 번만 바꿀거면 그냥 main문 안에다가
1
2
3
4
5
int a = 4;
int b = 5;
int temp = a;
a = b;
b = temp;
temp 변수 하나 만들어서 여기에 임시로 a값 저장하고 a에 b값 씌우고 b에 temp값 씌우면 된다.
근데 값을 여러번 바꿔야되면? 이 부분을 일일히 복붙해서 수정해서 적을건가?
아니지 않는가. 그래서 함수를 쓰는거다.
두번째 이유는
- 함수에는 return 값이 하나밖에 올 수 없으니까 포인터를 매개변수로 받아서 함수 내에서 원본 변수 값을 바꾸는거다.
만약 포인터 없이 그냥 아래처럼 함수를 작성하면
1
2
3
4
5
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
변수간에 값이 안 바뀐다.
왜냐면 main함수에서 실행 된 변수는 함수 컨택스트니까 스택 구간에 저장된다. 근데 swap도 함수다. 고로 얘도 스택 구간에 저장된다. 근데 이 swap에 저장되는 주소값하고, main에서 저장되는 주소값하고는 다르다. 그냥 값만 복사하는거다.
결론적으로 주소값이 다 다르기 때문에 동일한 메모리 주소에서 받아와서 값을 변경해주기 위해서 포인터를 사용해서 주소를 갖고오고 연산자로 그 주소의 값을 불러오는거다.
사실 다른 언어에서도 포인터는 다 존재한다. 다만 숨겨져있는 것일뿐.
참고자료
http://cslibrary.stanford.edu/102/PointersAndMemory.pdf