글 거의 다 썼다가 두 번은 다 갈아 엎었습니다...


지난번처럼 잘 설명된 글의 링크를 첨부하고 이를 바탕으로 이해하기 쉽게 재서술하겠습니다.



Call by Reference on 나무위키

ㄴ 나무위키에 작성된 call by reference 글입니다. 읽어보시길 권합니다.(어려울 수 있습니다)





첫번째 예시) call by value의 예시입니다.

void justFunc(int num) {
	num++;
}

void main() {
	int n = 0;
	justFunc(n);
	printf("%d", n);

}

결과 : 0


인자로 전달 받은 수에 1을 더하는 justFunc를 실행해도 n의 값은 바뀌지 않습니다.

이는 call by value, 즉 값에 의한 호출로, 함수를 호출할 때 값(n)을 복사해서 매개변수(num)로 피호출 함수(justFunc)에 넘겨줍니다.


따라서 값을 복사해서 넘겨주었으므로, main함수에서 변수(n)은 변하지 않으며, justFunc의 매개변수 num만이 바뀌게 됩니다.




그러나 다른 함수(보통 사용자 지정 함수)를 통해 변수(n)를 변경하고 싶은 경우가 있었고, 그래서 사용하는 방식이 call by reference(call by address)입니다.


두번째 예시) 

void justFunc(int* p) {
	(*p)++;
}



void main() {
	int n = 0;

	justFunc(&n);
	printf("%d", n);

}

결과 : 1

------------------------------------------------------------------------------------------------------------------------------------------------------------------------


justFunc를 실행하고 main함수의 변수 n의 값이 1로 바뀝니다. 

n의 주소를 복사해서 매개변수(p)로 넘겨주고 p(n의 주소)가 가르키는 것, 즉 n의 값을 +1함으로써 다른 함수에서의 변수의 값을 변경하였습니다.


  이렇게 피호출 함수(justFunc)가 호출 함수(main)의 변수에 영향을 미치는 경우를 주로 call by reference, 참조에 의한 호출 이라고 하곤 합니다.




하지만 정확하게 말하면 이는 call by reference가 아니고 call by address라고 불립니다. 그리고 이것은 사실 call by value를 사용한 것입니다.


왜냐하면 다른 함수에서의 변수를 변경한건 맞으나, 이 또한 값을 복사한 매개변수(여기선 주소값)를 함수에 넘겨준 것이기 때문이죠.





지금부터는 좀 더 깊게 들어가서 call by value, call by address, call by reference의 차이점에 대해 알아보겠습니다.


우선 용어를 명확하게 하고 들어가겠습니다.


방금 첫 번째 예시에서 justFunc(n); 을 했을 때 호출한 주체인 함수 main을 호출 함수라 합니다.

그리고 호출 당한 함수 justFunc를 피호출 함수라 합니다.


호출 함수(main)에서 피호출 함수(justFunc)에 전달한 것(n)을 실질 매개변수(actual parameter)라 합니다.

피호출 함수(justFunc)에서 num을 형식 매개변수(formal parameter)라 합니다.





Call by address vs Call by reference


위에서 제가 두 번째 예시를 call by address라 했습니다. 이는 실 매개변수(&n)로 주소값을 전달하고, 이를 복사한 값이 형식 매개변수(p)에 들어가는 방식으로 작동하였고, 이는 말 그대로 '주소에 의한 호출'이기 때문입니다. 또한 값을 복사해서 전달했으므로 call by value, 값에 의한 호출이기도 하죠.


그러면 call by reference는 대체 뭐냐?


일단 결론부터 말하면 C에는 call by reference가 존재하지 않습니다. call by reference가 뭔지 제대로 알고 싶으면 c++을 입문하고 제가 올린 나무위키 링크의 예제를 보시길 바랍니다.


간단히만 말하자면 일단 call by reference는 call by address, call by value와 달리 실질 매개변수를 제외하고는 변수(메모리)를 추가로 사용하지 않습니다.


첫 번째 예시를 보면 실질 매개변수 n을 제외하고 형식 매개변수 num을 추가로 사용하면서 메모리를 사용합니다.

두 번째 예시를 보면 실질 매개변수 n을 제외하고 형식 매개변수 p를 추가로 사용하면서 메모리를 사용합니다. 혹시 헷갈리시면 p의 주소값과 n의 주소값을 비교해보시길 바랍니다. 주소값이 다르며 따라서 다른 변수라는 것을 알 수 있습니다.


그러나 call by reference는 저 둘과 다르게 변수를 추가로 사용하여 메모리를 사용하지 않고, c++의 기능 중 하나인 '참조자 &'라는 것을 이용하여 오직 실질 매개변수만으로 호출하고 합니다.




Call by value vs Call by reference


call by value와 call by reference의 차이점은 다음과 같이 세 가지입니다.


1. 복사한 값을 전달한다 vs 복사가 아닌 실질 매개변수 그 자체를 전달한다.

2. 호출 함수에 영향을 미치지 못한다 vs 호출 함수에 영향을 미칠 수 있다.

3. 인자(실질 매개변수)를 다루는 메모리의 위치가 다르다(형식 매개변수의 메모리 위치) vs 인자를 다루는 메모리의 위치가 같다(실질 매개변수의 메모리 위치)


이를 바탕으로 이제 call by value와 call by reference와 call by address를 구분하면 다음과 같습니다.




Call by address는 복사한 값(주소값)을 전달한다는 점과 인자를 다루는 메모리의 위치가 다르다는 점에서 Call by value, 그래서 결론적으로 Call by value가 맞습니다.


하지만 호출 함수에 영향을 미칠 수 있다는 점에서 Call by reference의 특성을 띄고, 그래서 많이들 Call by reference로 여기고 사용하고는 합니다.


그러므로 이번 기회에 정확하게 알고 가되, 남들과 소통할 땐 이런 점을 감안해서 이해하시기를 바랍니다.





추가로 잘 정리된 블로그 링크 올립니다. 도움이 되시길 바랍니다.


잘 정리된 블로그 바로가기

+ Recent posts