값에 의한 호출(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

+ Recent posts