데이터 공유
이때까지 특정 기능의 명령을 묶어서 함수로 만들어서 사용하였는데, 이 함수 사이에 데이터를 공유하는 법은 무엇일까?
1. 값을 복사해서 전달하는 방법
가장 일반적인 방법은 값을 복사해서 전달하는 것이다.
이 방법은 함수를 호출할 때 변수뿐만 아니라, 상수나 수식도 사용할 수 있고, 지금까지 여러 차례 사용했던 방식이다.
이 방법은 호출된 함수가 반환된 이후에도 호출한 함수에 있는 변수의 값은 변하지 않는다 ( 호출된 함수의 기능과 상관없이 호출된 함수의 변숫값은 그대로 이다. )
- 10을 더하기 위해 값을 인수로 주는 경우
#include <stdio.h>
void add_ten(int a);
int main(void)
{
int a = 10;
add_ten(a);
printf("a : %d\n", a);
return 0;
}
void add_ten(int a)
{
a = a + 10;
}
이처럼, 호출되는 함수에 값을 복사하여 전달하는 방식은 값을 출력하거나, 연산하는 경우와 같이 호출하는 함수의 값을 바꿀 필요가 없는 경우에 사용한다.
2. 주소를 전달하는 방법
함수를 호출할 때 처리할 변수의 주소를 넘기는 방법도 있다.
포인터 연산으로 값을 처리해야 하기 때문에 값을 전달하는 방법보다 불편하다.
하지만, 주소를 전달하면 호출한 함수의 변숫값을 바꿀 수 있다.
- 포인터를 사용해서 변수 값에 10을 더하기
#include <stdio.h>
void add_ten(int* pa); //매개변수로 포인터 pa 선언
int main(void)
{
int a = 10;
add_ten(&a); // a의 주소를 인수로 준다.
printf("a : %d\n", a); // 증가된 a 값 출력
return 0;
}
void add_ten(int* pa) // 포인터 pa가 a의 주소를 받는다.
{
*pa = *pa + 10; // 포인터 pa가 가리키는 변수의 값 10 증가
}
매개변수 pa에 간접 참조 연산자를 사용하면 main함수에 있는 a를 사용할 수 있으며, 그 값을 바꾸는것도 가능해진다.
값을 복사해서 전달하는 방식 VS 주소를 전달하는 방식
1. 값을 복사해서 전달하는 방식
원본 데이터 보전 가능하기 때문에 안전성을 담보로 하는 상황에 유용
원본 데이터 수정 목적의 경우 사용법이 제한적
2. 주소를 전달하는 방식
원본 데이터를 바꿀 때 유용하나, 사용법이 복잡하고, 잘못 다루면 문제가 생길 수 있다.
따라서, 꼭 필요한 경우에만 사용한다.
3. 주소를 반환하는 함수
반환값이 있는 함수는 호출한 한수로 값을 복사해서 반환한다.
함수 안에서 사용한 지역 변수는 함수가 반환되면 저장 공간이 사라지므로, 그 값을 복사하여 반환해야 호출한 함수에 사용할 수 있다.
그러나, 함수가 반환된 후에도 변수의 저장 공간이 계속 유지 된다면, 주소를 반환하여, 호출하는 함수에서 쓸 수 있다.
즉, 정적 지역 변수와 전역 변수는 주소를 반환할 수 있다.
- 주소 반환하여 두 정수의 합 계산
#include <stdio.h>
int* sum(int a, int b);
int main(void)
{
int* resp;
resp = sum(10, 20);
printf("두 정수의 합 : %d\n", *resp);
return 0;
}
int* sum(int a, int b)
{
static int res; // 정적 지역 변수
res = a + b;
return &res;
}
/*
[ 출력 ]
두 정수의 합 : 30
*/
호출하는 함수가 주소를 주고 호출하듯이, 호출되는 함수도 주소를 반환할 수 있다.
호출한 함수에서는 그 값을 포인터에 저장하고, 간접 참조 연산을 수행하여, 언제든지 두 정수의 합을 사용할 수 있다. 또한, resp가 가리키는 변수 res의 값을 바꾸는 가능하다.
주소를 반환하는 함수를 만들 때 주의할 점
1. 반환값의 자료형은 반환값을 저장할 포인터의 자료형과 같아야 한다.
함수가 int형 변수의 주소를 반환하면, 값을 저장할 포인터는 int *형으로 선언해야하며, 함수의 반환형도 int* 형이 되어야 한다.
2. 지역 변수의 주소를 반환해서는 안 된다.
정적 지역 변수의 경우 함수가 반환 된 후 저장 공간이 계속 유지되기 때문에 호출한 함수에서 포인터 연산을 통해 언제든지 그 변수를 사용할 수 있다.
하지만, 일반 지역 변수는 함수가 반환되면 저장 공간이 회수되어 언제 다른 용도로 재활용될지 모르기 때문에 지역 변수의 주소를 반환하면 안된다.
이의 경우 컴파일러가 경고 메시지로 알려준다.
warning C4172 : 지역 변수 또는 임시 변수의 주소를 반환하고 있습니다.
결론, 주소를 반환하여 쓸 수 있는 경우는 그 주소를 다시 반환할 수 있다.
1. 정적 지역 변수 나 전역 변수의 주소를 반환한 경우
2. 호출하는 함수에 있는 변수의 주소를 인수로 받은 경우
[ 마지막 정리 ]
1. 값을 복사해서 인수로 전달하면, 허출하는 함수의 값은 바뀌지 않는다.
2. 호출하는 함수의 값이 바뀌려면 주소를 인수로 전달해야 한다.
3. 정적 지역 변수나 전역 변수와 같이 함수가 반환된 후에도 저장 공간이 유지되는 경우만 주소를 반환환다.
[ 표로 정리 ]
- 여러 가지 데이터 공유 방법
'Language > C' 카테고리의 다른 글
C_Char01. 프로그램과 C언어 (0) | 2021.06.05 |
---|---|
C_Char13-1. 변수 사용 영역 (0) | 2021.05.10 |
C_Char09.포인터(이해) (0) | 2021.05.09 |
C_Char09.포인터(개념) (0) | 2021.05.09 |