💡이번에는 함수의 인자 전달, 함수의 호출방식 등에 대해서 알아보자
call by value의 기본 호출 방식은 값의 복사이다.
#include <stdio.h>
void sub (int v);
int main (void)
{
int i= 100;
sub(i);
printf("i=%d\n", i);
return 0;
}
void sub (int v)
{
v = 200;
}
/*
<결과>
i= 100
*/
call by value와 반대되는 개념
변수의 복사본이 함수로 전달되는 것이 아닌, 원본의 주소값을 통해 직접 전달
함수의 호출 방식으로 함수를 호출하면서 주소값을 전달
전달된 주소가 가리키는 원본 변수의 조작이 함수 내에서 직접 가능
#include <stdio.h>
void sub (int v);
int main (void)
{
int i= 100;
sub(&i);
printf("i=%d\n", i);
return 0;
}
void sub (int *v)
{
*v = 200; //본 예제에서는 return값이 없어서 전역에선 바뀌지 않는다
}
/*
<결과>
i= 100
*/
예시 ) swap() 함수
swap함수 내에서 포인터를 사용하더라도 swap의 지역 변수를 가리키기 때문에 main함수 값에 영향을 주지 않음
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int val1 =10, val2 = 20;
swap(val1, val2);
printf("val1, vla2 : %d, %d\n", val1, val2);
return 0;
}
void swap(int a, int b)
{
int temp;
int *pa, *pb;
pa = &a;
pb = &b;
temp = (*pa);
(*pa) = (*pb);
(*pb) = temp;
printf("a, b : %d, %d \n", a, b);
}
/* 결과
a, b = 20, 10
val1, val2 = 10, 20
*/
scanf("입력 받을 문자의 서식", 변수의 주소)
→ 사용자의 입력값을 받는 함수//ex) scanf("%d, %d", &num1, &num2); //입력받는 형식이 "%d, %d"이므로 10, 20와 같이 입력해야 함 scanf("%d %d", &num1, &num2); //입력받는 형식이 "%d %d"이므로 10 20와 같이 입력해야 함
scanf
함수 호출시 변수에 &를 붙이는 이유?
- scanf 함수로 main에 있는 val 변수에 값을 저장한다고 하자.
- scanf 함수 내에서 main 함수에서 선언된 지역 변수 val에 접근하기 위해서는 해당 변수의 주소를 알아야한다.
- 따라서 scanf 함수를 호출하면서 값이 채워질 지역 변수 val의 주소값을 인자로 전달하는 것이다.
- 요약 : Call-By-Reference를 이용해야 여러개의 변수에 값을 저장할 수 있기 때문!
배열의 경우 일반 변수처럼 값 전체를 복사하는 방법을 사용할 수 없다.
따라서 배열의 주소를 넘겨서 접근하도록 유도하는 방법을 사용한다.
#include <stdio.h>
void fct(int *arr2);
int main(void)
{
int arr1[2] = {1, 2};
fct(arr1); //배열의 주소를 전달 (배열이름이 포인터)
printf("arr1[0] : %d \n", arrr1[0]);
printf("arr1주소 : %d \n", arr1);
return 0;
}
void fct(int *arr2)
{
printf("arr2[0] : %d \n", arr2[0]);
printf("arr2주소 : %d \n", arr2);
arr2[0] = 3;
}
/* <결과
arr2[0] : 1
arr2주소 : 1245020
arr1[0] : 3
arr1주소 : 1245020
*/
배열 전달시 주의점
배열의 주소만 전달하기 때문에 배열의 크기를 알 수가 없다.
배열의 주소를 인자로 전달할 경우 주소와 함께 크기를 보내는 것이 좋다.
//배열의 총합 출력하기
#include <stdio.h>
int ArrAdder(int *pArr, int n);
int main(void)
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int sumArr;
sumArr = ArrAdder9arr, sizeof(arr)/sizeof(int));
printf ("배열의 총합 : %d\n", sumArr);
return 0;
}
int ArrAdder(int *pArr, int n)
{
int sum = 0;
int i;
for(i=0; i<n; i++) sum+=pArr[i];
return sum;
}
/*
<결과>
배열의 총합 : 55
*/
//배열의 최대값 출력하기
#include <stdio.h>
int MaxVal(int pArr[], int n); /*int prr[] 과 int *pArr은 완전히 같은 선언이다.
둘 다 int형 포인터 변수이지만 int pArr[]는 매개 변수에서만 선언 가능하다.
int pArr[]을 함수 내부에서 선언 하려면 초기화가 필요 하다. */
int main(void)
{
int arr[10] = {4,8,3,7,2};
int maxA;
maxA = MaxVal(arr, sizeof(arr)/sizeof(int));
printf ("최대 값 : %d\n", maxA);
return 0;
}
int MaxVal (int pARr[], int n)
{
int max, i;
max = pArr[0];
for (i=1; i<n; i++)
if (max < pArr[i])
max = pARr[i];
return max;
}
/*
<결과>
최대 값 : 8
*/
#include <stdio.h>
void pswap (int *p1, int *p2);
int main()
{
int A = 10, B = 20;
int *pA, *pB;
pA = &A;
pB = &B;
printf("함수 호출전\n");
printf("pA : %d\n", *pA);
printf("pB : %d\n", *pB);
pswap(pA, pB);
printf("\n함수 호출 후\n");
printf("pA : %d\n", *pA);
printf("pB : %d\n", *pB);
return 0;
}
void pswap (int *p1, int *p2)
{
int *temp;
temp = p1;
p1 = p2;
p2 = temp;
}
/*
<결과>
함수 호출전
pA : 10
pB : 20
함수 호출후
pA : 10
pB : 20
*/
pswap
함수는 pA
와 pB
의 주소값을 복사에 의해 전달 받았을 뿐이다.p1
, p2
가 서로 값을 바꾸어도 지역변수이기 때문에 pA
, pB
는 기존의 값을 그대로 유지하게 된다.#include <stdio.h>
void pswap (int **p1, int **p2);
int main()
{
int A = 10, B = 20;
int *pA, *pB;
pA = &A;
pB = &B;
int *p1, *p2;
p1 = &pA;
p2 = &pB;
printf("함수 호출전\n");
printf("pA : %d\n", *pA);
printf("pB : %d\n", *pB);
pswap(p1, p2);
printf("\n함수 호출 후\n");
printf("pA : %d\n", *pA);
printf("pB : %d\n", *pB);
return 0;
}
void pswap (int **p1, int **p2)
{
int *temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
/* <결과>
함수 호출전
pA : 10
pB : 20
함수 호출후
pA : 20
pB : 10
*/