C 언어에서 함수는 값에 의한 호출(Call by Value)과 참조에 의한 호출(Call by Reference), 두 가지 방식으로 호출할 수 있습니다. 어떤 방식을 선택하느냐에 따라 함수 간 데이터 통신 방식이 달라지므로, 상황에 맞는 올바른 선택이 중요합니다.
- 호출된 함수 안에서 실제 매개변수(실인수)의 값이 변경되지 않아야 한다면 → 값에 의한 전달(Pass by Value)을 사용합니다.
- 호출된 함수 안에서 실제 매개변수의 값이 변경되어야 한다면 → 참조에 의한 전달(Pass by Reference)을 사용합니다.
- 함수가 두 개 이상의 값을 반환해야 하는 경우에도 참조에 의한 호출을 통해 값을 간접적으로 돌려줄 수 있습니다.
예제 코드: 여러 값 한 번에 반환하기
다음은 포인터를 활용해 하나의 함수에서 두 개의 값을 동시에 반환하는 C 프로그램입니다. 원의 반지름을 입력받으면 넓이와 둘레를 함께 계산하여 메인 함수로 전달합니다.
#include <stdio.h>
void areaperi(int x, float *p, float *q) {
*p = 3.14 * x * x; // 넓이 계산
*q = 2 * 3.14 * x; // 둘레 계산
}
void main() {
void areaperi(int, float *, float *);
int r;
float a, p;
printf("원의 반지름을 입력하세요:\n");
scanf("%d", &r);
areaperi(r, &a, &p); // 주소를 전달 (참조에 의한 호출)
printf("넓이 = %f\n", a);
printf("둘레 = %f", p);
}
실행 결과
위 프로그램을 실행하면 다음과 같은 출력을 확인할 수 있습니다.
원의 반지름을 입력하세요: 5 넓이 = 78.50000 둘레 = 31.40000
함수 areaperi()는 반환값이 없는 void 함수임에도 불구하고, 포인터를 통해 넓이와 둘레라는 두 개의 결과값을 호출자에게 전달했습니다. 이것이 바로 참조에 의한 호출의 강력한 장점입니다.
포인터 이해를 위한 핵심 포인트
- 포인터는 반드시 타입을 가집니다. 포인터는 단순히 '포인터 타입' 하나로 존재하는 것이 아니라, int형을 가리키는 포인터, float형을 가리키는 포인터처럼 특정 자료형에 종속됩니다.
- 모든 포인터의 크기는 동일합니다. 가리키는 자료형이 무엇이든 포인터 변수 자체의 크기는 같으며, 일반적으로 int형의 크기와 같습니다(32비트 시스템에서는 4바이트, 64비트 시스템에서는 8바이트).
- 포인터는 메모리 주소를 저장합니다. 모든 포인터는 컴퓨터 메모리상의 한 위치에 대한 주소를 담고 있지만, 그 주소가 가리키는 변수의 실제 크기는 자료형에 따라 서로 다를 수 있습니다.