블로그는 귀차니즘

First Sensation
  • 공지
  • 지역로그
  • 태그
  • 방명록

일반적인 오류 - Call By Reference in C??

Language 2008/03/10 21:01 귀차니스트
  우리는 세상을 살다보면 흔히 오류를 범하곤 합니다. 범위확대의 오류등이 여기에 속할 수 있죠. 그런데 C 에서 웹 서핑중 하나의 오류를 발견했습니다. 포인터를 전달하여 함수를 호출할 때 흔히 Call By Reference 라고 부르더군요. 잘못되었는데 왜 이렇게 부를까라고 생각이 들었습니다. 그리고 부랴부랴 검색을 해봤더니 많은 곳에서 그렇게 지칭하고 있었습니다.
  알고보면 실제로 C 언어에서는 Call By Reference 라는 것을 지원하고 있지 않습니다. 다만 Pointer 를 이용한 Call By Value 를 통하여 Call By Reference 를 흉내내는 것 뿐이죠. 다만 C 에서 지원하지 않는 Reference 문법을 C++ 에서는 & 를 이용하여 지원하고 있습니다.

PointerReference.cpp (Language : cpp)
  1. int swap( int *a, int *b );
  2. int swap( int &a, int &b );

  위 함수의 차이가 무엇일까요?? 밑 함수는 C++ 에서 지원하는 Reference 문법입니다. 고로 호출시 int a = 10; 인 상태에서 swap( a, a ) 이렇게 호출을 하고, swap 함수 안에서 a에 대해서 값을 변경하게 되면 즉각적으로 a = 10; 에 대한 값이 변경되게 됩니다.
  그렇다면 위의 swap( int *a, int *b );에 대하여 swap( &a, &a ); 이렇게 호출을 한다면 어떻게 될까요?? 이 것은 단순한 변수로 생각할 수 있습니다. 왜냐구요? swap 함수안에서 a 에 대한 값을 변경하기만 해보시죠.

Pointer.cpp (Language : cpp)
  1. int swap( int *a, int *b )
  2. {
  3.     b = NULL;
  4.     return *a;
  5. }

  컴파일 시에는 아무런 문제가 발생하지 않습니다. 다만 b 에 대하여 역참조를 실시할 경우 Memory Access Violation이 발생하겠죠. a 와 b 가 그저 단순한 Pointer 변수라는 것에 대하여 생각이 드시나요?? 알고 계시는 분이 많으시겠지만, int *a 라는 것은 단순한 Pointer 변수이기 때문에 바로 Call By Value 를 * 연산자를 통한 역참조로 Call By Reference 를 흉내내는 것입니다.
  뭔가 지지부진하고 현실상에서 중요하지 않은 옛날 옛적의 이야기일 수도 있지만 나름 중요하다고 느꼈기 때문에 포스팅을 해봅니다.
크리에이티브 커먼즈 라이센스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

"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
2008/03/10 21:01 2008/03/10 21:01
TAG C, C++, Call By Reference, Call By Value, Reference, 참조
받은 트랙백이 없고, 댓글 6개가 달렸습니다.

트랙백 주소 :: http://www.filewiki.net/tc/trackback/29

댓글을 달아 주세요

  1. 최민수 2008/10/10 11:26  댓글주소  수정/삭제  댓글쓰기

    지나가다가...우선 글 잘 읽었습니다.
    이해가 안가는 부분이 있는데 설명 부탁드립니다. ^^;;

    "call by reference를 흉내냈다"라는 표현을 쓰셨는데,
    그럼 call by reference의 매커니즘?은 정확히 어떻게 되는 것입니까?

    C++의 reference 문법은 말로 설명하셨고, C의 포인터변수를 예로 들어 주셨는데 같은 예제로 설명을 해주셨으면 이해가 빠를 것 같은데요. '';;

    http://kldp.org/node/52502
    위 사이트의 맨 마지막 글을 보면 레퍼런스를 다루는 방법에 있어서C++ compiler 또한 C의 그것과 다를게 없다고 하는 데 맞는 말인가요?

    • 귀차니스트 2008/10/12 04:49  댓글주소  수정/삭제

      음 안녕하세요^^.

      다른 일 때문에 최근 관리를 잘 하지못해 답변이 조금 늦었습니다.
      일단 정말 여기서 얘기하는 Call By Reference라고 하는 것은 엄밀히말해서 정말 Reference라고 부르긴 힘듭니다. 정확하게 얘기한다면 Call By Pointer쯤 이라고 하면 되려나요??

      계속되는 내용은 아래 댓글에 적도록 하겠습니다.

  2. 최민수 2008/10/10 11:51  댓글주소  수정/삭제  댓글쓰기

    추가로,
    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에 놓고 운전하는 것을 흉내내는 것인가요?

    • 귀차니스트 2008/10/12 04:57  댓글주소  수정/삭제

      네..
      실제로 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++ 에서는 그 것이 불가능하기 때문이죠.

  3. 지나가다 2008/12/18 14:27  댓글주소  수정/삭제  댓글쓰기

    귀차니스트님...

    Call-By-Reference를 지원하는 언어라... ㅎㅎ

    제가 알고있기로는 Pointer를 쓰나 Reference를 쓰나 Address를 참조(Reference)하여 함수인자를 넘겨주는 방식을 모두 Call-By-Reference라고 합니다.

    즉, 함수인자를 넘겨줄때 값으로 넘겨주는 것이 아니라 주소값으로 넘겨준다면 모두 Call-By-Reference라는 것이죠..

    어차피 함수를 부를때 참조해야 하는 것은 Value나 Address일테고 이 두 방식을 구별하기 위해 나온 개념이
    Call-By-Value, Call-By-Reference라는 개념입니다.

    제가 알고있는 개념이 잘못됐다면
    C, C++의 창시자인 Bjarne Stroustrup의 개념이 잘못된 것이고,
    그 많은 C, C++ Language책을 썼던 대가들의 개념이 잘못된 것입니다.

    Call-By-Reference로 부를 수 있는 두 가지 방식은 pointer를 사용하는 방식과 reference를 이용하는 방식이 있다라고 보시는 것이 좋을 것 같네요

    • 귀차니스트 2008/12/18 20:52  댓글주소  수정/삭제

      음.. 그럴수도 있습니다.

      제가 생각하는 언어적 측면에서 Reference와 실제 Call By Reference 라는 개념정의 자체가 다를 수 있으니까요.

      하지만 누가 옳다 그르다를 떠나서 대가들이 앞에서 사용하고 정의했다고 해서 계속하여 그 것으로 불러야 한다고 볼 수는 없지 않을까요?

      제가 생각하는 언어적 Reference 개념 자체와 호출 형식을 비교하면 실질적으로 다르게 불러야 한다고 옳기 때문에 이런 글을 적은 것이죠. 사실 내부 구현의 관점에서 본다면 Pointer, Reference 둘 다 Call By Reference 라고 부를 수도 있지만 컴파일러가 사용하는 구현 개념은 사실 언어 사용자에게 옵션일 뿐 필수는 아니라고 생각하기 때문입니다.

      만약 Reference 그 자체의 개념만을 생각하여 한다면 어떨까요?.. 저는 그 물음에 대하여 위 글과 같은 결정을 내린것 뿐이죠^^;

3n+1 Problem

Algorithm 2008/02/17 08:30 귀차니스트
  1. 문제링크 : http://icpcres.ecs.baylor.edu/onlinejudge/index.php?option=com_onlinejudge&Itemid=8&category=3&page=show_problem&problem=36 
  2.  의   경   : 처음으로 나오는 쉬운 기초적인 문제입니다. 하지만 체크해야될 조건이 있습니다. 바로 입력 숫자의 크기가 서로 바뀔 수 있다는 점이죠.
    입력 방식이 10 20과 같이 입력될 때에는 괜찮으나 20 10과 같이 입력될 때에는 체크를 꼭 해주어야 합니다.
  3. 소스
    100.c (Language : c)
    1. #include <stdio.h>
    2.  
    3. int Calculation( int number );
    4.  
    5. int main( int argc, char **argv )
    6. {
    7.     int StInput, EnInput;
    8.     int StartNum, EndNum, RetValue;
    9.  
    10.     int i, MaxCycle;
    11.     while( scanf( "%d %d", &StInput, &EnInput ) == 2 ) {
    12.         if( StInput > EnInput ) {
    13.             StartNum = EnInput;
    14.             EndNum = StInput;
    15.         }
    16.         else {
    17.             StartNum = StInput;
    18.             EndNum = EnInput;
    19.         }
    20.         MaxCycle = 0;
    21.         for( i = StartNum; i <= EndNum; i++ ) {
    22.             RetValue = Calculation( i );
    23.             if( RetValue > MaxCycle )
    24.                 MaxCycle = RetValue;
    25.         }
    26.         printf( "%d %d %d\n", StInput, EnInput, MaxCycle );
    27.     }
    28.     return 0;
    29. }
    30.  
    31. int Calculation( int number )
    32. {
    33.     int CycleLength;
    34.     for( CycleLength = 1; number != 1; CycleLength++ ) {
    35.         if( number == 1 )
    36.             break;
    37.         if( number % 2 == 1 ) {
    38.             number = number * 3 + 1;
    39.         }
    40.         else {
    41.             number = number >> 1;
    42.         }
    43.     }
    44.     return CycleLength;
    45. }


크리에이티브 커먼즈 라이센스
Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.

"Algorithm" 분류의 다른 글

Algorithm Traning Book - 다섯번째 문제 (0)2008/06/15
Algorithm Traning Book - 세 번째 문제 (0)2008/06/10
Algorithm Traning Book - 두 번째 문제 (0)2008/06/09
The Blocks Problem (0)2008/02/17
Maximum Sum (0)2008/02/17
2008/02/17 08:30 2008/02/17 08:30
TAG ACM, ACM-ICPC, C, ICPC
받은 트랙백이 없고, 댓글이 없습니다.

트랙백 주소 :: http://www.filewiki.net/tc/trackback/3

댓글을 달아 주세요

◀ 이전페이지 1 다음페이지 ▶

블로그 이미지
First Sensation 귀차니스트
rss
  • 관리자
  • 글쓰기

카테고리

  • 전체 (110)
    • Computer (3)
    • Language (14)
    • Reverse Engineering (1)
    • Algorithm (9)
    • TopCoder (3)
    • Library (2)
    • Programming (19)
    • Programming Tip (9)
    • PSP-Programming (10)
    • Program (5)
    • Small Talk (31)
    • Document (4)

최근에 올라온 글

  • Gradient 작성중에 있습.... (3)
  • 게임&인터랙티브 애플리....
  • 한게임 자동테트리스 Ve.... (24)
  • Intel 64 And IA32 Arch.... (2)
  • 한게임 자동테트리스 Ve.... (24)

최근에 달린 댓글

  • 다운어덯게 받아요. difl 2008
  • 멋있네요 ㅎㅎ. 준호씨 2008
  • ^^; 그러셨군요.. 사실 동영.... 귀차니스트 2008
  • ㅋㅋ 속도 튜닝의 무서움 ㅜ.... 귀차니스트 2008
  • 관리자만 볼 수 있는 댓글입.... 비밀방문자 2008

달력

«   2009/01   »
일 월 화 수 목 금 토
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

링크

  • kkamagui 프로그래밍 세상.
  • 류광의 번역 이야기.
  • 서광열의 프로그래밍 언....
  • 준호씨의 블로그.
  • 최익필의 이름없는 블로그.
  • 위키는 귀차니즘.

최근에 받은 트랙백

  • 궁극의 예외처리. 이름없는 블로그 2008
  • Maximum sum. 티스토리 지점 2008

글 보관함

  • 2008/12 (1)
  • 2008/11 (4)
  • 2008/10 (2)
  • 2008/09 (3)
  • 2008/08 (5)

태그목록

  • ACM
  • STL
  • COM
  • Warcraft3
  • multimap
  • Call By Reference
  • 병렬처리
  • GDI
  • 개발
  • TopCoder
  • boost::array
  • Chaos
  • XML
  • iterator_traits
  • Directive
  • 파티션
  • 램
  • 디자인패턴
  • 계발
  • Image
  • HTML 파서
  • Pangya
  • OpenMP
  • VCL
  • Call By Value
  • HTML Parser
  • std::copy
  • ACM-ICPC
  • 1.35
  • DP

지역로그 : 태그 : 방명록 : 관리자 : 글쓰기
귀차니스트’s Blog is powered by Textcube 1.7.5 : Risoluto / Designed by DesignNia.net