[C] 함 수 - 2
5. call by value, call by reference(address)

아래 예제를 보자!

#include

void swap(int a,int b);

void main(void)
{
int a=5,b=6;
swap(a,b);
printf("%d,%d ",a,b);
}

void swap(int a,int b)
{
int tmp;
tmp=a;
a=b;
b=tmp;
}

위 예제는 swap()를 실행하여 a,b에 저장된 값을 교환하고자 하는 예제이다. 그러나 실행결과를 보면 바꾸지 않았음을 확인해 볼수 있다.
아래 그림은 이상황을 정확하게 보여주고 있다.



그림을 보면 swap()이 호출(실행)되면 main()내의 a,b란 변수 속의 값으로 swap()내에 a,b란 변수를 생성하고 복사하는 것을 볼수 있다. 또한 swap()함수내에서 a,b는 그함수 내에서만 사용이 가능하며 그 사용이 다른 함수에 영향을 주지 않음을 보여 준다. 이러한 함수의 호출을 call by value라 한다.

#include

int a=5,b=6;

void swap(void);

void main(void)
{
swap(a,b);
printf("%d,%d ",a,b);
}

void swap(void)
{
int tmp;
tmp=a;
a=b;
b=tmp;
}

위 소스는 전역변수로 a,b를 선언(정의)하여서 이문제를 해결하고 있다. 그러나 앞으로 swap()를 사용하려면 같은이름의 변수(int a,b)를 항상 선언하여 사용해야 한다. 이말은 swap()함수의 사용을 어렵게 하면 프로그래머가 이사실을 항상 기억해 두어야 한다. 부자연스럽기도 하고 이런식으로 함수를 계속 정의한다면 전역변수의 양이 많아지고 전역변수의 양이 많아 진다는 말은 실행중인 프로그램의 메모리 점유률이 높아진다는 말이다. 결국 좋은 프로그래밍이라고 할수 없게 된다.

단순히 리턴형을 사용할수 없음에 유의하자! 이말은 리턴되어지는 인수의 갯수가 한개라는 말이다. 두개의 값을 교환하여 두개의 변수를 리턴하지 못한다는 것이다. 이런점에 착안하여 아래와 같이 소스를 수정해 보았다.

#include

int *swap(int a,int b);

void main(void)
{
int a=5,b=6,c[2];
c=swap(a,b);
a=c[0];
b=c[1];
printf("%d,%d ",a,b);
}

int *swap(int a,int b)
{
int tmp;
int c[2];
tmp=a;
a=b;
b=tmp;
c[0] = a;
c[1] = b;
return c;
}

위 예제는 그러나 실행해 보면 에러를 만나게 된다. 원인은 c=swap(a,b);에서 c값이 배열이란데 있다. 즉, 리턴형이 물론 포인터형으로 배열도 포인터라고 했으니 사용할수 있을 것 같지만 안된다. 왜일까? 왼쪽에 오는 값은 항상 하나의 자료형이어야 한다. 즉, 배열처럼 다수의 자료형이 올수 없다는 말이다. 그럼 포인터로 받으면 어떻게 될까?

int a=5,b=6,*d;

d=swap(a,b);

a = *d;

b = *(d+1);

위와 같이 해보아도 문제가 된다. 왜냐하면, 리턴해준 swap()내의 c[]가 swap()실행후 메모리를 반환해 버리기 때문에 정확한 값을 리턴받는다는 보장이 없다. 위와 같이 간단한 예제는 제대로 실행될 것이다. 그러나, 반환된 메모리상으로 어떤 함수나 값이 침입하면 어떤 결과가 나올지 예상할수 없다. *d는 반환된 메모리상의 값을 가르키고 있고 이메모리는 어떤 함수나 값에의해 사용될수 있게 때문이다. 더욱이 군더더기 같은 많은 값들의 선언이 있었다. 한마디로 어거지성 프로그램이다. 이런 프로그램은 버그가 내재된 폭탄과 같다.

그럼 해결책이 없는가?

아래 예제를 보자!

#include

void swap(int *a,int *b);

void main(void)
{
int a=5,b=6;
swap(&a,&b);
printf("%d,%d ",a,b);
}

void swap(int *a,int *b)
{
int tmp;
tmp=*a;
*a=*b;
*b=tmp;
}

위 소스를 실행해 보면 바뀌어진 두값을 확인해 볼수 있다. 이경우는 swap()에게 주소를 넘겨주었다. swap()내에서 a,b는 main()내의 a,b를 가르키고 있는 포인터이며, swap()내의 a,b에 대한 값을 변화시킨다는 것은 main()내의 a,b의 값을 변화시키는 의미를 갖는다. 위의 어떤 소스와 비교해 보아도 훌륭한 방법임을 알수 있다. 이런 호출방식을 call by reference 또는 call by address라 한다.

물론 이방식에서 프로그래머는 swap()에 인수를 사용할때는 반드시 주소값을 넘겨주어야 한다는 사실을 알고 있어야 한다. 이런 대표적인 함수가 scanf()이다.

이로써 함수를 작성할때에는 호출함수내의 자료에 변화를 주고자 하는지 리턴값만 받으면 되는지 아니면 전혀 별개로 동작해도 되는지의 여부에 따라 함수의 형을 결정해 주어야 함을 알수 있게 되었다.
by 지니yo | 2005/02/23 17:13 | C/C++ | 트랙백 | 덧글(0)
< 이전페이지 다음페이지 >