우리는 세상을 살다보면 흔히 오류를 범하곤 합니다. 범위확대의 오류등이 여기에 속할 수 있죠. 그런데 C 에서 웹 서핑중 하나의 오류를 발견했습니다. 포인터를 전달하여 함수를 호출할 때 흔히 Call By Reference 라고 부르더군요. 잘못되었는데 왜 이렇게 부를까라고 생각이 들었습니다. 그리고 부랴부랴 검색을 해봤더니 많은 곳에서 그렇게 지칭하고 있었습니다.
알고보면 실제로 C 언어에서는 Call By Reference 라는 것을 지원하고 있지 않습니다. 다만 Pointer 를 이용한 Call By Value 를 통하여 Call By Reference 를 흉내내는 것 뿐이죠. 다만 C 에서 지원하지 않는 Reference 문법을 C++ 에서는 & 를 이용하여 지원하고 있습니다.
위 함수의 차이가 무엇일까요?? 밑 함수는 C++ 에서 지원하는 Reference 문법입니다. 고로 호출시 int a = 10; 인 상태에서 swap( a, a ) 이렇게 호출을 하고, swap 함수 안에서 a에 대해서 값을 변경하게 되면 즉각적으로 a = 10; 에 대한 값이 변경되게 됩니다.
그렇다면 위의 swap( int *a, int *b );에 대하여 swap( &a, &a ); 이렇게 호출을 한다면 어떻게 될까요?? 이 것은 단순한 변수로 생각할 수 있습니다. 왜냐구요? swap 함수안에서 a 에 대한 값을 변경하기만 해보시죠.
컴파일 시에는 아무런 문제가 발생하지 않습니다. 다만 b 에 대하여 역참조를 실시할 경우 Memory Access Violation이 발생하겠죠. a 와 b 가 그저 단순한 Pointer 변수라는 것에 대하여 생각이 드시나요?? 알고 계시는 분이 많으시겠지만, int *a 라는 것은 단순한 Pointer 변수이기 때문에 바로 Call By Value 를 * 연산자를 통한 역참조로 Call By Reference 를 흉내내는 것입니다.
뭔가 지지부진하고 현실상에서 중요하지 않은 옛날 옛적의 이야기일 수도 있지만 나름 중요하다고 느꼈기 때문에 포스팅을 해봅니다.
알고보면 실제로 C 언어에서는 Call By Reference 라는 것을 지원하고 있지 않습니다. 다만 Pointer 를 이용한 Call By Value 를 통하여 Call By Reference 를 흉내내는 것 뿐이죠. 다만 C 에서 지원하지 않는 Reference 문법을 C++ 에서는 & 를 이용하여 지원하고 있습니다.
위 함수의 차이가 무엇일까요?? 밑 함수는 C++ 에서 지원하는 Reference 문법입니다. 고로 호출시 int a = 10; 인 상태에서 swap( a, a ) 이렇게 호출을 하고, swap 함수 안에서 a에 대해서 값을 변경하게 되면 즉각적으로 a = 10; 에 대한 값이 변경되게 됩니다.
그렇다면 위의 swap( int *a, int *b );에 대하여 swap( &a, &a ); 이렇게 호출을 한다면 어떻게 될까요?? 이 것은 단순한 변수로 생각할 수 있습니다. 왜냐구요? swap 함수안에서 a 에 대한 값을 변경하기만 해보시죠.
컴파일 시에는 아무런 문제가 발생하지 않습니다. 다만 b 에 대하여 역참조를 실시할 경우 Memory Access Violation이 발생하겠죠. a 와 b 가 그저 단순한 Pointer 변수라는 것에 대하여 생각이 드시나요?? 알고 계시는 분이 많으시겠지만, int *a 라는 것은 단순한 Pointer 변수이기 때문에 바로 Call By Value 를 * 연산자를 통한 역참조로 Call By Reference 를 흉내내는 것입니다.
뭔가 지지부진하고 현실상에서 중요하지 않은 옛날 옛적의 이야기일 수도 있지만 나름 중요하다고 느꼈기 때문에 포스팅을 해봅니다.
"Language" 분류의 다른 글
| boost::spirit - Parser 라이브러리 (0) | 2008/04/23 |
| std::ostreambuf_iterator, std::istreambuf_iterator의 이유 (1) | 2008/04/16 |
| std::auto_ptr - Smart Pointer 이지만?? (1) | 2008/04/13 |
| C# Application - Main 에서 Try-Catch 오작동 해결하는 방법 (4) | 2008/04/07 |
| Boost 1.35 - 워크샵 뒤의 포스팅 (2) | 2008/04/03 |


댓글을 달아 주세요
지나가다가...우선 글 잘 읽었습니다.
이해가 안가는 부분이 있는데 설명 부탁드립니다. ^^;;
"call by reference를 흉내냈다"라는 표현을 쓰셨는데,
그럼 call by reference의 매커니즘?은 정확히 어떻게 되는 것입니까?
C++의 reference 문법은 말로 설명하셨고, C의 포인터변수를 예로 들어 주셨는데 같은 예제로 설명을 해주셨으면 이해가 빠를 것 같은데요. '';;
http://kldp.org/node/52502
위 사이트의 맨 마지막 글을 보면 레퍼런스를 다루는 방법에 있어서C++ compiler 또한 C의 그것과 다를게 없다고 하는 데 맞는 말인가요?
음 안녕하세요^^.
다른 일 때문에 최근 관리를 잘 하지못해 답변이 조금 늦었습니다.
일단 정말 여기서 얘기하는 Call By Reference라고 하는 것은 엄밀히말해서 정말 Reference라고 부르긴 힘듭니다. 정확하게 얘기한다면 Call By Pointer쯤 이라고 하면 되려나요??
계속되는 내용은 아래 댓글에 적도록 하겠습니다.
추가로,
http://sookmyung.ac.kr/~hyoin01/h7.html
위 사이트의 한 내용입니다.
"C 언어에서는 원칙적으로 call-by-value 만을 허용한다.
그러나 변수의 주소를 추출하는 방법이 주어지기 때문에 call-by-reference 기법을 프로그래머가 실지로 구현할 수 있다."
저도 흉내 냈다기 보다 call by reference를 구현했다는 표현이 맞는 것 같아서요.
C++에서는 그 기능을 사용하기 편리하게 wrapping해서 reference 문법을 추가한게 아닐까요?
유치한 예를 하나 들면,
자동차 옵션의 하나인 수동기어와 자동기어를 봤을 때,
---- 자동기어: "D" (drive mode)를 제공 함
---- 수동기어: drive mode 제공 안함
수동기어 자동차를 가진 사람이 기어를 2단, 3단, 4단 변속하는 것이 자동기어를 가진 사람이 D에 놓고 운전하는 것을 흉내내는 것인가요?
네..
실제로 C 언어에서는 Call By Reference 라는 것을 지원하지 않습니다. 문법자체에서 그렇게 되어있는 것이죠. 그리하여 주소를 이용한 방법으로 값을 바꾸는 방법이 제공되나. 엄밀히 말하면 Reference라고 부르긴 힘들다고 생각이 되네요. 하지만 일반적으로 처음 수업을 듣게 되면 Call By Reference라고 가르키는 곳이 많기에 그렇게 적은겁니다.
정말 원리를 따지고 본다면 C++ 언어에서 지원하는 int &a 와 같은 reference 문법또 한 내부적으로는 Pointer 를 이용한 값 변경뿐입니다. 이 것은 exe 파일을 만든 후, 그 파일을 실행시켜 동작하는 부분으로 이동하여 어셈블링을 하게 되면 볼 수 있습니다.
언어라는 것이 컴퓨터에서 실행 가능한 명령어로 바꾸기 위해 문법적으로 작성하는 일종의 문장이다보니 실제 변경이 되었을 때에는 타겟플랫폼에 따라서 달라질 수도 있겠죠. 하지만 x86환경에서는 주소 참조를 이용한 값 변경이 가능하고, 그로 인해 reference를 사용하게 된다면 함수의 예로 들었을 때, 함수의 인자로 전달되는 값을 바꾸려면 reference 문법을 실제 내부적으론 Pointer를 이용한 값 변경이 일어나게 될 수 밖에 없죠^^.
그래서 말씀그대로 C++ 에서는 불편한 점이 있었던 Pointer를 Reference로 감쌌다고 볼 수도 있습니다.
마지막으로 논지와는 조금 벗어나지만 C++ 에서 지원하는 Reference는 정말 Reference라고 보기는 힘듭니다. 다른 언어( ex- C#, Java ... )등에서 지원하는 Primitive Type( C, C++에서는 Built-in Type)을 제외하고는 모두 reference type이라 하여 개체를 핸들링 할 수 있고, null을 지정할 수 있으나 C++ 에서는 그 것이 불가능하기 때문이죠.