본문 바로가기
Language&Framework&Etc/C

포인터와 함수에 대한 이해(14-1) 함수의 인자로 배열 전달하기

by 머리올리자 2020. 12. 8.

인자전달의 기본방식은 값의 복사이다

- "함수호출 시 전달되는 인자의 값은 매개변수에 복사가 된다"

 

- 위 문장에서 가장 중요한 단어는 '복사'이다.

 

- 즉, 복사가 되는 것 뿐이기 때문에 함수가 호출되고 나면, 전달되는 인자와 매개변수는 별개가 된다.

 

int simplefunc(int num){......}

int main(void)
{
	int age=17;
    simplefunc(age); // age에 저장된 값이 매개변수 num에 복사됨
}

- 위 코드의 simplefunc 함수 호출을 통해서 인자로 age를 전달하고 있음.

 

But..

 

- "실제로 전달되는 것은 age가 아닌, age에 저장된 값임"

- 그리고 그 값이 매개변수 num에 복사되는 것.

 

- age와 num은 값을 주고받은 사이일 뿐 그 이상은 아무런 관계도 아니다.

 

- "simplefunc 함수 내애서 매개변수 num에 저장된 값을 1 증가시킬 경우, 변수 age의 값은 얼마가 증가하는가"

→ 변수 age의 값은 증가하지 않는다.

→ 왜??? num과 age는 별개의 변수이기 때문이다.

 

그럼 이어서...

 

함수호출 시 인자로 배열을 통째로 전달하는 방법에 대해서 생각.

그러나... 함수를 호출하면서 매개변수에 배열을 통째로 넘겨주는 방법은 존재하지 않는다.

 

왜? → "매개변수로 배열을 선언할 수 없음"

 

배열을 통째로 넘겨받으려면 매개변수로 배열을 선언할 수 있어야 한다.

→ 이것이 허용되지 않기 때문에 배열을 통째로 넘기는 것은 불가능

 

대신!

 

함수 내에서 배열에 접근할 수 있도록 배열의 주소값을 전달하는 것은 가능

 

(여기까지 보면 포인터의 존재 이유가 배열을 편하게 다루려고 만든 것 같다는 생각이.....)

 

 

배열을 함수의 인자로 전달하는 방식

- 아파트를 보고 싶어 하는 사람 앞에 아파트를 복사해다 놓을 수 없다면, 아파트의 주소를 가르쳐줘서 직접 찾아가게 하면 됨.

 

즉...

 

- 배열을 통째로 전달하는 것이 불가능하다면, 배열의 주소값을 인자로 전달해서 이를 통해서 접근하도록 유도하는 방법을 생각해볼 수 있다. 

 

다음과 같은 배열이 있다면,

int arr[3]={1,2,3};

 

다음의 형태로 함수를 호출하면서 배열의 주소 값을 전달할 수 있음

SimpleFunc(arr); // SimpleFunc 함수를 호출하면서 배열 arr의 주소 값 전달

 

그렇다면 SimpleFunc 함수의 매개변수 선언?

int main(void)
{
	int arr[3] = {1,2,3};
	int* ptr= arr; // 배열이름 arr은 int형 포인터
}

따라서 SimpleFunc 함수의 매개변수는 다음과 같이 int형 포인터 변수로 선언되어야 한다.

void SimpleFunc(int* param) {......}

param을 이용해서 배열 접근?

printf("%d %d", param[1], param[2]);

 

예제.

#include <stdio.h>

void showarr(int*, int);

int main(void)
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 4,5,6,7,8 };
	showarr(arr1, sizeof(arr1) / sizeof(int));
	showarr(arr2, sizeof(arr2) / sizeof(int));

}

void showarr(int* param, int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", param[i]);
	printf("\n");
}

그렇다면 출력아닌 값의 변경도 가능?

 

가능하다!

 

예제.

 

#include <stdio.h>

void showarr(int*, int);
void addarr(int*, int, int);

int main(void)
{
	int arr[] = { 1,2,3 };
	
	addarr(arr, sizeof(arr) / sizeof(int), 1);
	showarr(arr, sizeof(arr) / sizeof(int));

	addarr(arr, sizeof(arr) / sizeof(int), 10);
	showarr(arr, sizeof(arr) / sizeof(int));

	addarr(arr, sizeof(arr) / sizeof(int), 100);
	showarr(arr, sizeof(arr) / sizeof(int));

}

void showarr(int* param, int len)
{
	for (int i = 0; i < len; i++)
		printf("%d ", param[i]);
	printf("\n");
}

void addarr(int* param, int len, int add)
{
	for (int i = 0; i < len; i++)
		param[i] += add;
}

- 이렇듯 배열의 주소 값만 안다면 어디서든 배열에 접근하여 저장된 값을 참조하고 변경할 수 있다.

 

배열을 함수의 인자로 전달하는 함수의 또 다른 선언

int형 배열의 주소 값을 인자로 받을 수 있도록 int형 포인터 변수 선언

void showarr(int* param, int len) {....}
void addarr(int* param, int len, int add) {....}

아래처럼 선언하는 것도 가능

void showarr(int param[], int len) {....}
void addarr(int param[], int len, int add) {....}

int param[] 과 int *param은 동일한 선언

 

다만, 전자의 선언이, 배열이 인자로 전달된다는 느낌을 더 강하게 주는 선언

일반적으로 배열의 주소 값이 인자로 전달될 때는 int param[] 형태의 선언을 주로 많이 씀

 

하지만, 이 둘이 같은 선언으로 간주되는 경우에는 매개변수의 선언으로 제한된다.

 

int main(void)
{
	int arr[3]={1,2,3};
	int* ptr=arr;    // int ptr[]=arr;로 대체 불가능
}

 

 

참고 : [윤성우 열혈 C 프로그래밍] - 대부분의 내용 및 코드는 이 책에서 개인 공부 정리 목적으로 참고하였습니다.