값에 의한 호출과 주소에 의한 호출
포인터와 함수에 대해 다루기 전, 우리가 사용하던 함수의 모양을 다시 살펴보자.
int odd_check (int x);
void greeting (int x);
포인터와 함수에 대해 공부하기 전 사용하던 함수들은
매개변수로 값을 받을 때, 변수의 값을 복사해서 함수를 호출하였다.
이것이 값에 의한 호출이다.
값에 의한 호출 : 변수의 값을 복사하여 함수를 호출하는 방식
이런 값에 의한 호출 방법의 특징은, 값을 복사해서 함수를 호출하기 때문에
받아온 값을 함수에서 변형하여도, main 함수에 있는 원래의 변수의 값은 그대로라는 것이다.
아래 코드의 예시를 살펴보자.
int func (int x, int y);
int main () {
int a = 10, b = 20, result = 0;
result = func(a, b);
printf("%d %d %d", a, b, result);
return 0;
}
int func (int x, int y) {
x = x / 10;
y = y / 10;
return x + y;
}
// 10 20 3
a, b 변수의 값을 복사하여 func 함수를 호출하였다.
func 함수에서 값을 변형시켰지만, main 함수의 a, b 변수의 값은 그대로이다.
그렇다면 주소에 의한 호출은 어떨까?
주소에 의한 호출 : 변수의 주소를 참조하여 함수를 호출하는 방식
int func (int *x, int *y);
int main () {
int a = 10, b = 20, result = 0;
result = func(&a, &b);
printf("%d %d %d", a, b, result);
return 0;
}
int func (int *x, int *y) {
*x = *x / 10;
*y = *y / 10;
return *x + *y;
}
// 1 2 3
위와 같은 상황인데, 호출 방식만 변경한 결과이다.
이렇게 주소를 참조하여 함수를 호출할 수 있다.
주소에 의한 호출의 필요성
1️⃣ 값에 의한 호출은 함수에게 인자를 전달할 시 사용되는 매개 변수가 너무 많다는 문제가 있다.
void func (int a1, int a2, int a3, int a4, int a5, int a6, int a7);
int main () {
int a = 10, b = 20, c = 30, d = 40, e = 50, f = 60, g = 70;
func(a, b, c, d, e, f, g);
return 0;
}
void func (int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
printf(“%d %d %d %d %d %d %d \n”, a1, a2, a3, a4, a5, a6, a7);
}
2️⃣ 배열이나 구조체와 같은 데이터를 함수에 전달할 때, 실행 시간이 단축되고 메모리 공간을 적게 차지한다.
int array[] = {10, 20, 30, 40, 50, 60, 70, 80};
func(array, sizeof(array) / sizeof(int));
이렇게 배열을 전달할 때, 배열의 시작 주소와 배열의 크기만 전달해주는 방식으로 사용할 수 있다.
배열 포인터를 이용한 주소에 의한 호출
2차원 배열을 함수에 전달하기 위해서는 배열 포인터를 사용해 주소에 의한 호출 방법을 사용할 수 있다.
void func (int (*p)[4], int num1, int num2); // 함수의 선언, 배열 포인터 변수
int main () {
int array[2][4] = {10,20,30,40,50,60,70,80};
func(array, sizeof(array) / 16, sizeof(array) / 8); // 함수의 호출
return 0;
}
void func (int (*p)[4], int num1, int num2) {
for (int i = 0; i < num1; i++) {
for (int j = 0; j < num2; j++) {
printf("%d ", p[i][j]);
}
printf("\n");
}
}
위는 2차원 배열을 전달받아, 열과 행의 형식으로 출력해주는 코드이다.
주소를 반환하는 함수
주소를 반환하는 함수는 이렇게 선언하고 정의한다.
int* func();
자료형과 참조 연산자, 함수 이름과 매개변수로 이루어져 있다.
int형 주소를 반환하는 func라는 의미이다.
주소를 반환하는 함수는 대량의 데이터를 반환할 때 사용한다.
주의할 점은 지역 변수의 주소를 반환하면 경고가 발생하므로 꼭 static 변수를 선언하고 그 주소를 반환해야 한다.
static (정적) 변수는 함수가 종료된 후에도 메모리 공간이 소멸되지 않는 변수이다.
아래 코드는 지역 변수의 주소를 반환하여 경고가 발생하는 경우이다.
int* input(); // 함수의 선언
int main() {
int *p = NULL;
p = input(); // 함수의 호출
printf("%d\n", *p);
return 0;
}
int* input( ) // 함수의 정의
{
int num1;
scanf("%d", &num1);
return &num1;
}
아래 코드에서 함수 속 num1을 정적 변수로 선언하여 경고를 제거하였다.
int* input(); // 함수의 선언
int main() {
int *p = NULL;
p = input(); // 함수의 호출
printf("%d\n", *p);
return 0;
}
int* input( ) // 함수의 정의
{
static int num1; // 정적 변수 선언
scanf("%d", &num1);
return &num1;
}
'C' 카테고리의 다른 글
[C] 포인터와 2차원 배열 (0) | 2023.10.26 |
---|---|
[C] 배열 포인터, 포인터 배열 (0) | 2023.10.26 |
[C] 포인터와 다차원 포인터 (0) | 2023.10.24 |
[C] C의 문자열, 문자 배열 (0) | 2023.10.18 |
[C] 조건 연산자 (삼항 연산자) 백준 2562 (0) | 2023.09.11 |