💡 자료구조

함수의 인자에 대해 알아보기(배열과 포인터)

ji-hyun 2021. 6. 10. 23:15

 

#include <stdio.h>
int main(void)
{
	int sum, i, average;
	int num[10];
	for (i = 0; i < 10; i++)
		scanf("%d", &num[i]);
	sum = calculate_sum(num);
	average = sum / 10;
	printf("%d\n", average);
	return 0;
}

int calculate_sum(int array[]) {  
	int sum, i;
	sum = 0;
	for (i = 0; i < 10; i++)
		sum = sum + array[i];
	return sum;
}

 

main() 안에 있는 sum = calculate_sum(num) 에서 num은 10의 길이를 가지는 배열이다. 배열의 이름은 첫번째 요소의 주소와 같다는 사실은 다 알고 있을 것이다. 하지만 정확히는 배열의 이름은 배열의 시작 주소와 같다는 의미가 더 정확하다. 밑에 그림을 참고해서 보자!

 

 

https://m.blog.naver.com/tipsware/220992959841

 

배열의 시작 주소라는 것이 딱 첫번째 요소의 주소만 가리키는 줄 알았는데 이 블로거 분의 글을 읽어보니 전체 배열의 시작 주소를 가리키는 말이라는 것을 깨달았다. 

 

 

 

 

 

이 때문에 처음의 코드와 같이 배열을 입력 인수로 넘기면 배열의 시작 주소를 자체를 넘기는 것과 같다.

이제 함수 안에서 int calculate_sum(int array[]) 에서의 매개변수는 무슨 의미일까?

밑에 예제를 통해서 다시 자세히 알아보겠다.

 

 

 

 

#include <stdio.h>
void upgrade_array(int x[]) // 배열의 주소가 x에 복사된다. 따라서 x를 통하여 배열 요소의 값을 변경할 수 있다. 매개변수를 정의할 때 int x[4]로 하여도 된다
{
	x[0] = 99;
}

int main(void)
{
	int a[] = { 10, 20, 30, 40 };
    upgrade_array(a);  // 배열의 이름은 배열의 주소(시작주소)이므로 주소가 전달된다.
    printf("a[0]= %d a[1]= %d, a[2]= %d \n", a[0], a[1], a[2]);
    
    return 0;
}

 

update_array(a) 와 같이 호출하면서 배열 a를 함수로 전달하였다. 그리고 함수 안에서 배열의 요소를 변경한다.

main()으로 돌아와서 배열 a[ ]의 요소들을 출력하여 보면 a[0]이 99로 변경된 것을 확인할 수 있다.

 

 

배열은 원본이 전달되는 것처럼 보인다! -> 왜 그럴까? 다시 말해서 배열의 이름 a는 배열 시작 주소를 가리키는 주소라고 하였다. 따라서 배열 a를 update_array()에 전달하면 배열의 주소가 변수 x에 복사되어서 원본이 전달되는 거나 마찬가지이다. 그래서 int x[ ] 이나 int x[4] 라고 써도 무방한 것이다.

 

 

 

 

 

 

참고 )

다음과 같은 2개의 함수 선언은 완전히 동일하다.

int sub( int para[] ); == int sub( int *para );

 

#include <stdio.h>
int main(void)
{
	int sum, i, average;
	int num[10];
	for (i = 0; i < 10; i++)
		scanf("%d", &num[i]);
	sum = calculate_sum(num);
	average = sum / 10;
	printf("%d\n", average);
	return 0;
}

int calculate_sum(int *array) {   // int array[] 라고 써도 동일
	int sum, i;
	sum = 0;
	for (i = 0; i < 10; i++)
		sum = sum + array[i];
	return sum;
}

 

맨 처음 코드에서 보았던 int array[ ] 를 int *array 라고 바꿔 써서 실행해도 결과는 동일하다.

 

논리적으로 생각해봅니다. 일단 배열의 시작 주소만 안다면 포인터는 배열의 모든 인덱스에 접근할 수 있습니다. 그 이유는 배열은 연속적인 메모리 구조를 갖고 있기 때문입니다. 

 

 

 

즉, 배열이름(=배열 시작주소)인 num 을 입력 인자로 넘기는 것과 포인터 변수 array를 매개변수로 받는 것으로 코딩해도 괜찮다는 것을 기억해두자!

 

 

 

 

 

 

 

참고 ) 크기 비교해보기

그리고 calculate 함수 내부에서 *array의 크기를 출력해보면 포인터의 크기인

4 byte가 나온다는 것을 확인 할 수 있다.

 

<수정한 소스>

#include <stdio.h>
int main(void)
{
	int sum, i, average;
	int num[10];
	for (i = 0; i < 10; i++)
		scanf("%d", &num[i]);

	printf("int num[10]의 크기: %d\n", sizeof(num));   // 추가한 부분

	sum = calculate_sum(num);
	average = sum / 10;
	printf("%d\n", average);
	return 0;
}

int calculate_sum(int *array) {
	int sum, i;
	sum = 0;

	printf("int *array의 크기 : %d\n", sizeof(*array));     // 추가한 부분
    
	for (i = 0; i < 10; i++)
		sum = sum + array[i];
	return sum;
}

출력결과

 

 

 

'💡 자료구조' 카테고리의 다른 글

시간 복잡도와 빅-오 표기법  (0) 2021.06.17
문자열  (0) 2021.06.16
동적할당 malloc 함수  (0) 2021.06.16
Binary Search vs Linear Search  (0) 2021.06.14
배열의 자료구조 기초  (0) 2021.06.09