간단한 포인터 연습이 나를 머리카락을 뽑게 만들었다
Source: Dev.to

나는 주어진 포인터 연습 문제에 대해 (손으로) 출력값을 적어 보라는 과제를 받았다. 겉보기엔 간단해 보였지만, 어느 단계에 이르렀을 때 나는 길을 잃었다. 생각할수록 혼란의 토끼굴에 빠졌고, AI에게 물어봐도 도움이 되지 않았다.
아래는 나를 당황하게 만든 예제, 내가 저지른 실수들, 왜 그것이 틀렸는지, 그리고 이번 경험을 통해 배운 원칙들이다.
Code
int f(int** r, int** s) {
int temp = r;
int temp2 = **s;
int *z = *r;
*r = *s;
*s = z;
printf("r = %d\n", r);
printf("s = %d\n", **s);
*z += 3;
**s -= 8;
**r -= 19;
return temp + temp2;
}
int main(void) {
int a = 80;
int b = 12;
int *p = &a;
int *q = &b;
int x = f(&p, &q);
printf("x = %d\n", x);
printf("*p = %d\n", *p);
printf("*q = %d\n", *q);
printf("a = %d\n", a);
printf("b = %d\n", b);
return EXIT_SUCCESS;
}
Expected Output
r = 12
s = 80
x = 92
*p = -7
*q = 75
a = 75
b = -7
Mistakes I Made
-
잘못된 반환값 – 나는
64를 반환했지만 정답은92였다.
5·6번째 줄에서temp와temp2는 각각r(포인터 값)과**s(정수12)의 값을 복사해서 초기화한다. 나는 이후**r와**s에 대한 연산이temp와temp2에 영향을 줄 것이라고 착각했다. 실제로 이 변수들은 독립적인 복사본이며, 값을 바꾸려면temp와temp2자체를 수정해야 한다(예:temp += 3). -
잘못된 주소를 변경 – 나는
main에서*p와*q가 가리키는 대상을 바꾸었지만, 실제로 바꿔야 할 것은f안에서*r과*s가 가리키는 대상이다. 스와핑은 함수에 전달된 포인터 자체에 영향을 주어야 한다. -
*z에 대한 오해 – 나는*z를 주소로 생각하고*z += 3이 “포인터를 세 칸 이동한다”는 의미라고 여겼다. 실제로*z는int(즉,z가 가리키는 값)이며,*z += 3은 그 정수에3을 더하는 연산이다. 주소가 바뀌는 것이 아니다.
이러한 오해 때문에 나는 계속해서 원을 그리며 헤맸다.
Takeaways
- 기본으로 돌아가기 – 포인터에 관한 입문 자료를 다시 읽어 보라.
- 모든 과정을 적어 보기 – 겉보기에 사소해 보이는 연산도 미묘한 디테일을 숨기고 있을 수 있다.
- 타입을 기억하라 – 현재 다루고 있는 것이 포인터인지, 포인터의 포인터인지, 실제 값인지 정확히 아는 것이 중요하다.
- 메모리 주소 시각화 – 메모리 레이아웃을 스케치하면 값과 주소를 혼동하는 일을 방지할 수 있다.