포인터는 변수의 주소를 나타낸다.
int a;
int *x;
*x = &a;
*
를 붙인다.x
라는 포인터가 변수 a
의 주소를 나타내기 위해서는 a
앞에 &
붙여 할당한다.일반적으로 함수를 사용하면 인자로 전달되는 값을 함수의 매개변수에 복사 후 사용한다. 따라서 함수 내에서 변수에 어떤 조작을 해도 원래의 변수에는 영향을 미치지 않는다.
대표적인 SWAP 예시
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
cout << a << " " << b << endl;
}
int main() {
int n = 1, m = 2;
swap(n, m);
cout << n << " " << m;
return 0;
}
// 출력
// 2 1
// 1 2
반면, 함수 내에서 원래 변수 값을 조작하고 싶은 경우가 분명 있을 것이다. 그럴 때는 주소값을 인자로 받아 포인터에 저장하거나, 인자의 주소값을 이용해 해결할 수 있다.
주소값을 인자로 받아 포인터에 저장하는 경우
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
cout << *a << " " << *b << endl;
}
int main() {
int n = 1, m = 2;
swap(&n, &m);
cout << n << " " << m;
return 0;
}
// 출력
// 2 1
// 2 1
받아온 인자의 주소값을 이용하는 경우
void swap(int &a, int &b) {
int temp = a;
a = b;
b = temp;
cout << a << " " << b << endl;
}
int main() {
int n = 10, m = 20;
swap(n, m);
cout << n << " " << m;
return 0;
}
// 출력
// 2 1
// 2 1
int arr[3] = {1, 2, 3};
int *x = arr;
cout << *x;
// 출력
// 1
arr
은 첫 번째 원소의 주소를 가리킨다.arr
을 할당하면 이 역시 첫 번째 원소의 주소를 가리키게 되고, 출력하면 arr[0]
값이 나온다.arr + 1, arr + 2, ...
로 표현할 수 있다.*(x + 1)
의 값은 2
가 된다.c++에서 배열 자체를 함수에 전달할 수는 없기 때문에, 특별한 처리가 필요하다. 바로 매개변수를 포인터로 지정하는 것이다.
void func(int *param) {
cout << param[0] << " ";
param[0] = 3;
cout << param[0] << " ";
}
int main() {
int arr[3] = {1, 2, 3};
func(arr);
cout << arr[0] << " ";
return 0;
}
// 출력
// 1 3 3
매개변수를 포인터로 지정하면, 인자에 배열 arr
을 넣었을 때 포인터 param
은 arr
의 첫 번째 원소의 주소를 받게 된다. 그리고 배열은 연속하여 주소가 할당되기 때문에 포인터 param
을 배열처럼 활용할 수 있다. 또 함수 내에서 배열의 주소값만을 다루기 때문에, 배열의 값을 변경하면 원본 배열의 값도 바뀐다.
매개변수 앞에 *
를 붙여 포인터로 지정했으나, int param[]
으로 작성할 수도 있다. 그리고 한눈에 인자가 배열임을 알 수 있으므로 가독성이 좋다.
python
에서는 특별히 타입을 정해줄 필요도, 포인터를 만들 필요도 없었기 때문에 크게 신경쓰지 않고 지나갔다. 그러나,pyhton
에서도 내부적으로 동일한 동작이 이루어지며, 함수 내에서 배열 값을 변경할 수 있는 것도 그 때문이란 것을 이번에 알았다. 사용하기 쉬운게 무조건 좋은 건 아닌 것 같다.