코딩에서 기초적이면서도 매우 중요한 개념입니다.
1. call-by-value
#include <stdio.h>
void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
int main() {
int a = 2, b = 3;
swap(a, b);
printf("a = %d, b = %d\n", a, b);
return 0;
}
위의 코드는 a와 b의 값을 바꾸어(swap) 출력하는 프로그램을 의도하여 작성한 코드입니다. 즉 a = 3, b = 2라는 출력을 기대한 코드입니다. 하지만 위 코드를 실행시켜 보면 이러한 의도대로 작동되지 않음을 확인할 수 있습니다. 이는 미리 정의한 swap 함수에서 매개 변수가 '값에 의한 호출(call-by-value)'의 원리로 실행되기 때문입니다. 이는 변수의 이름(tag; a, b)을 신경 쓰지 않고 변수 내에 저장된 값(value)만을 고려하여 호출이 이루어진다는 의미입니다. 따라서, swap 함수를 정의할 때 매개 변수 x와 y를 통해 변수 a와 b가 직접 연결되는 것이 아니라, 변수 a, b 내에 저장된 값 2와 3이 연결되기 때문에 의도대로 프로그램이 실행되지 않는 것으로 볼 수 있습니다.
2. call-by-reference
#include <stdio.h>
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main() {
int a, b;
scanf_s("%d %d", &a, &b);
swap(&a, &b);
printf("a = %d, b = %d\n", a, b);
}
본래의 의도에 걸맞은 프로그램을 작성하기 위해서는 '참조에 의한 호출(call-by-reference)'의 개념을 활용해야 합니다. '참조에 의한 호출'이란 포인터 개념을 활용하여 main 함수 내 변수 a, b와 swap 함수의 매개 변수 x와 y를 이어주는 것을 의미합니다. 단순히 포인터를 써야 한다고 기계적으로 암기할 것이 아니라 '참조에 의한 호출'이 이루어지는 원리를 이해하는 것이 중요하다고 봅니다.
위와 같이 프로그램을 작성할 경우, 변수 x에는 변수 a의 주소 &a가 저장되고, 변수 y에는 변수 b의 주소 &b가 저장됩니다. 즉, 변수의 주솟값을 참조하여 x에 a, 그리고 y에 b를 각각 연결한 것입니다. 그러므로 *x는 &a라는 주소에 저장된 값을 의미하게 되고 *y는 &b라는 주소에 저장된 값을 의미하게 됩니다. 따라서 *x와 *y라는 값을 변경하여도 이들이 &a와 &b라는 주소에 저장되어 있다는 정체성은 변함없을 것입니다. 그렇기 때문에 main 함수에서 a와 b를 호출할 때 변경된 값이 올바르게 출력되는 것입니다.