본문으로 이동

미디어위키 1.45 안정화가 거의 끝났습니다. 다만 Flow 확장 기능 관련 이슈가 있어서 대체하는 작업을 수행할 계획입니다.

  1. 큰숲백과:청사진에서 위키 발전의 대략적인 방향성을 제시했습니다. 의견이 있으신 분은 큰숲백과토론:청사진에서 의견을 남겨주시면 좋겠습니다.
  2. 기능상의 오류로 지원하지 않고 있는 기능에 대해서는 큰숲백과토론:이슈 트래커에 요약했습니다. 참고하시기 바랍니다.
  3. 데이터베이스 덤프 받고싶으신 분은 큰숲백과 가입 후에 사용자토론:Bigforest에 의견 남겨주시면 ftp 주소, 계정, 비밀번호를 특수:EmailUser를 통해서 공개할 예정입니다.

작은숲:위키노트/초보자를 위한 C 언어 강의/값에 의한 호출과 참조에 의한 호출

큰숲백과, 나무를 보지 말고 큰 숲을 보라.

C 언어에서 함수가 차지하는 비중은 상당히 크다. 이 함수를 쓰는데 있어서 알아야할 것이 몇가지 있다. 그중에 하나가 값에 의한 호출과 참조에 의한 호출이다. 이 두가지는 함수를 호출할 때 매개변수를 넘겨주는 방법에 해당된다. 함수는 하나의 공작기계와 같다. 어떤 기계든지 일을 하기 위해서는 재료가 필요하다. 그 재료를 가지고 적절한 일을 한 다음에 그 결과물을 내놓는 것이 기계이다. 프로그래밍 언어에서 함수도 이와 동일한 일을 한다. 함수가 일을 할 수 있도록 넘겨주는 재료를 우리는 매개변수라고 부른다. 그리고, 함수가 일을 한 후에 넘겨주는 결과물을 반환값이라고 한다. 이렇게 함수가 일을 할 수 있도록 어떤 값을 넘겨줘야 하는데, 가끔은 이게 문제가 될 때가 있다. 일반적으로 우리가 함수를 사용할 때, 함수의 매개변수로 값을 넘겨준다. 아래 함수를 보도록 하자.

void swap(int x, int y)
{    int t;
    t = x;
    x = y;
    y = t;
}void main()
{    int x = 10, y = 20;
    swap(x, y);
    printf("x = %d, y = %dn", x, y);
}

이미 눈치 챘겠지만 위에서 swap() 함수가 하는 일은 두 수의 값을 서로 바꾸는 것이다. 그럼 swap() 함수를 호출한 다음 printf() 함수에서 출력되는 값은 무엇일까? 우리가 원하는 것은 x와 y의 값이 바뀌는 것이니,

x = 20, y = 10

이렇게 되야 정상이다. 하지만, 실제로 실행해보면 이렇게 되지 않는다.

x = 10, y = 20

이렇게 나온다. 왜 그럴까? 이건 우리가 원하는 결과가 아니다. 그렇다면 뭐가 잘못된 것일까? 쉽게 생각했을 때, swap() 함수를 호출하면서 x와 y를 매개변수로 넘겨줬다. 하지만, 이때 swap() 함수에 넘어가는 것은 x와 y, 두 변수가 넘어가는 것은 아니다. 이 두 변수에 저장되어 있는 값이 넘어가는 것이다. 따라서, swap() 함수에서의 x, y는 넘어온 값, 즉 main() 함수 내에서의 x와 y의 값을 넘겨받게 된다. 이것을 "값에 의한 호출"이라고 말한다. 그렇다면 생각해봐야 할 것이 main() 함수에서의 x, y와 swap() 함수의 x, y는 같은 것일까? 아니다. 이 두 함수는 다른 블럭이다. C 언어에서는 블럭이 달라지면, 아무리 같은 이름의 변수라고 할지라도 서로 다른 변수이다. 즉, 다른 메모리 공간을 이용한다는 말이다. 실제로 하나의 블럭에서 변수가 선언되면 그 블럭이 끝나기 전까지 그 변수를 위한 공간이 할당되다가, 블럭이 종료됨과 동시에 변수를 위해 할당됐던 공간은 지워지게 된다. 이런 변수들을 자동변수라고 부른다. 우리가 일반적으로 사용하는 변수들이 바로 자동변수이다. 위에서 main() 함수와 swap() 함수에서의 x, y는 같은 이름을 가지고 있지만 다른 변수이다. 즉 메모리상에서 서로 다른 저장공간을 갖는다. 다만 swap() 함수가 호출되어 동작을 시작하기 전까지는 같은 값을 가지고 있을 것이다. 이제 swap() 함수가 실행을 시작하고 두 값이 서로 바뀌었다. 그렇다면 swap() 함수 내의 변수들은 바뀐 값을 가지게 된다. 즉, swap() 함수 내에서 출력을 해보면 바뀐 값을 확인해볼 수 있다. 하지만, swap() 함수 내에서의 변수들의 값이 바뀌었다고 할지라도 main() 함수에서의 x, y의 값도 바뀌는 걸까? 서로 다른 변수들이니까 그럴 리는 없다. 즉, 우리가 원한 것은 swap() 함수를 호출함으로서 main() 함수에 있는 x, y의 값을 바꾸는 것이다. 위 예제에서는 단지 swap() 함수에서의 x, y의 값만 서로 바꾸고 마는 것이다. 그리고 swap() 함수가 실행을 마치고 리턴하게 되면 그 값은 영원히 사라지게 된다. 그렇다면 어떻게 해야 swap() 함수가 우리가 원하는대로 제대로 동작을 할까? 여기에서의 문제는 함수가 리턴할 수 있는 값이 하나뿐이라는데 있습니다. 리턴할 수 있는 값이 하나라는 건 종종 복잡한 문제가 될 수도 있습니다. 바로 swap() 함수에서처럼 두 값을 바꾼 다음에 리턴을 시켜서 main() 함수에 있는 x, y를 변경시켜줘야할텐데 그렇지 못하는 게 문제이다. 이것을 해결할 수 있는 방법이 C 언어에서는 '참조에 의한 호출'이라는 것이 있다. '참조'라는 말을 어디서 들어봤을까? 아마 들어봤을 것이다. 포인터를 공부하는 중에 참조 연사자(*)를 비롯해서 참조한다는 말을 들어봤을 것이다. 바로 해결 방법은 포인터이다! 포인터를 이용해서 변수 그 자체를 함수의 매개변수로 넘겨주는 것이다. 실제로는 변수 그 자체라기보다는 변수의 주소를 넘겨준다는 말이 더 정확할 것이다. 하지만 변수의 주소를 함수의 매개변수로 넘겨주게 되면, 넘겨받은 함수에서는 그 주소를 이용해서 호출한 곳에서 선언된 변수를 사용할 수 있게 된다. 그 변수의 주소에 직접 값을 저장시킬 수도 있고, 그 값을 읽어올 수도 있다. '참조에 의한 호출'로 swap() 함수를 바꿔보면 아래와 같다.

void swap(int *x, int *y)
{    int t;
    t = *x;
    *x = *y;
    *y = t;
}void main()
{    int x = 10, y = 20;
    swap(&x, &y);
    printf("x = %d, y = %dn", x, y);
}

이와 같이 main() 함수에서 swap() 함수를 호출할 때는 x, y 변수의 주소를 매개변수로 넘겨주고, swap() 함수에서는 이 주소들을 넘겨받아 포인터 변수 x, y에 저장시킨다. 이렇게 함으로써 swap() 함수에서 main() 함수의 x, y의 값을 직접 건드릴 수 있다. 이제 main() 함수에서 출력을 해보면 결과가 원하는대로 나올 것이다.

x = 20, y = 10

이와 같이 참조에 의한 호출을 이용하면 함수가 호출된 곳의 변수를 마치 자기 것인양 사용할 수 있다. 물론 참조 연산자(*)를 사용해서 말이다. 이렇게 참조에 의한 호출을 이용하면 반환값이 하나밖에 되지 않는다는 함수의 한계를 넘어설 수 있다. C 언어에서 포인터라는 것은 C 언어를 어렵게 만들기도 하지만, C 언어가 엄청난 힘을 가지도록 만들어주는 아주 유용한 것이다. C 프로그래밍 실력을 늘으실려면 무엇보다도 이 포인터를 완벽하게 이해하는 것이 중요하다.

이 작은숲 문서의 출처는 위키노트의 위키노트: 문서입니다.