값에 의한 호출(call-by-value)
f_sum() 함수를 호출할 때 a값이 전달되어 begin에 저장되며, b 값이 전달되어 end에 저장된다.
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
int f_sum(int begin, int end);
int main()
{
int a, b, sum; //지역변수
printf("a ~ b까지의 합 구하기 \n");
printf("a는? ");
scanf("%d", &a);
printf("b는? ");
scanf("%d", &b);
sum = f_sum(a, b); //함수호출
printf("\n%d ~ %d의 합은 %d", a, b, sum);
return 0;
}
int f_sum(int begin, int end)
{
int i, sum;
sum = 0;
for (i = begin; i <= end; i++)
{
sum += i;
}
return sum;
}
f_sum()함수에서 main()의 인수 a를 전달받은 begin 변수는 a와 같은 값을 가진다.
f_sum()함수에서 return sum; 직전에 begin = begin * 2;를 실행하여 begin 값을 변경하면 main()의 a값도 변할까?
a와 begin은 서로 다른 함수에서 선언하여 다른 기억장소를 사용하기 때문에 a는 변하지 않는다.
f_sum() 함수를 int f_sum(int a, int b)로 정의하여도 매개변수 a는 동명이인에 해당하므로 다른 기억장소를 사용한다.
이 방식은 호출된 함수에서 자신을 호출한 함수의 인수를 절대로 변경할 수 없으므로 함수를 호출할 때 마음 놓고 자신의 정보를 전달할 수 있다. 이 '함수 간 독립성 보장'이라는 특징 때문에 함수 호출 시 기본적으로 사용하는 인수 전달 방식이 '값에 의한 호출'이다.
이해를 돕기 위한 예시
내 노트를 복사 >>> 각자 내용이 같은 노트를 갖게 된다.
코드 예시
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
#define N 5
int f_even(int no);
int main()
{
int i, marble[N] = { 5, 4, 2, 3, 7 };
for (i = 0; i < N; i++)
{
if (f_even(marble[i]) == 1)
{
printf("%d: 홀수\n", marble[i]);
}
else
{
printf("%d: 짝수\n", marble[i]);
}
}
return 0;
}
int f_even(int no)
{
if (no % 2 != 0)
{
return 1;
}
else
{
return 0;
}
}
주소에 의한 호출(call-by-value)
배열 전체를 함수에 전달할 때는 주소에 의한 호출 방식만 사용한다.
원소가 천 개인 배열 전체를 값에 의한 호출 방식으로 전달한다고 가정해보자.
인수인 배열의 원소 개수만큼 값을 저장할 매개변수의 기억장소가 필요하고, 배열 원소 순서대로 매개변수에 값을 저장하는데 시간이 걸린다.
배열은 대량의 자료를 저장하는 데 사용하므로 이 배열을 값에 의한 호출로 전달한다면 추가적 기억장소와 값 복사로 인한 자원 낭비가 데이터 양에 비례하여 커진다.
그래서 배열은 원본을 공유하는 주소에 의한 호출 방식을 사용한다.
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
#define N 5
int f_tot(int ary[N]);
int main()
{
int kor[N] = { 45, 34, 43, 33, 48 };
printf("총계: %d \n", f_tot(kor));
return 0;
}
int f_tot(int ary[N])
{
int i, sum;
sum = 0;
for (i = 0; i < N; i++)
{
sum += ary[i];
}
return sum;
}
배열 인수: 차원과 상관없이 배열명만 사용
>> 배열명은 배열 시작 주소이므로 결국 주소를 전달하는 방식
배열 매개변수 선언: 전달되는 배열의 차원에 맞게 배열 선언
주의
- 배열은 함수 간에 같은 기억장소를 공유하므로 호출된 함수 f_tot()에서 ary배열 원소를 변경하면 main()의 kor 배열 원소가 변경된다. >> 함수에서 배열 내용을 변경한 후 배열을 반환할 필요가 없다.
- 매개변수 배열 선언 시
1차원 배열이라면 int ary[N] 대신 int ary[ ]처럼 원소수 생략 가능
2차원 배열이라면 int b[5][7]대신 int b[ ][7]처럼 행 개수 생략 가능
- f_tot() 함수는 원소 개수가 N개일 때만 사용할 수 있다. 원소 개수와 상관없이 총계를 구하는 함수는 나중에 배울 예정.
배열을 전달하여 모든 원소를 두 배로 변경하기
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
#define N 5
void f_double(int ary[N]);
int main()
{
int i, kor[N] = { 45, 34, 43, 33, 48 };
f_double(kor);
for (i = 0; i < N; i++)
{
printf("%4d", kor[i]);
}
return 0;
}
void f_double(int ary[N])
{
int i;
for (i = 0; i < N; i++)
{
ary[i] *= 2;
}
}
예시
노트 원본을 빌려주므로 노트는 공유하는 한 권만 있게 되는 경우
함수 호출 시 결과를 저장할 빈 배열을 추가로 전달하기
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
#define N 5
void f_twice(int a[N], int a_twice[N]);
void f_print(int ary[N]);
int main()
{
int i, kor[N] = {45, 34, 43, 33, 48};
int kor_twice[N];
f_twice(kor, kor_twice);
f_print(kor);
f_print(kor_twice);
}
void f_twice(int a[N], int a_twice[N])
{
int i;
for (i = 0; i < N; i++)
{
a_twice[i] = a[i] * 2;
}
}
void f_print(int ary[N])
{
int i;
for (i = 0; i < N; i++)
{
printf("%d ", ary[i]);
}
printf("\n");
}
void형 함수면 return; 생략가능
#include <stdio.h>
#pragma warning(disable: 4996)
#pragma warning(disable: 6031)
double get_average(int ary[], int n);
int main()
{
int a[4] = { 92, 80, 75, 93 };
int b[3] = { 88, 57, 81 };
printf("a 평균: %5.1f \n", get_average(a, sizeof(a) / sizeof(a[0])));
printf("b 평균: %5.1f \n", get_average(b, sizeof(b) / sizeof(b[0])));
return 0;
}
double get_average(int ary[], int n)
{
int i, sum;
sum = 0;
for (i = 0; i < n; i++)
{
sum += ary[i];
}
return (double) sum / n;
}
'프로그래밍 > C,C++' 카테고리의 다른 글
포인터 예제 (0) | 2024.06.11 |
---|---|
포인터 (0) | 2024.06.06 |
문자열 처리 (0) | 2024.05.28 |
인수 전달하는 함수 (0) | 2024.05.28 |
인수 전달하지 않는 함수 (0) | 2024.05.27 |