2013년 10월 1일 화요일

함수의 인자로 배열이 올 때

C언어의 대부분의 기본 서적에는 함수에 대하여, 그리고 배열에 대하여 자세히 설명이 되어 있으나 함수의 인자(parameter)로 배열이 오는 경우에 대하여 설명이 되어 있는 곳이 거의 없어 이 곳에서 이야기하고자 한다.

다음 소스를 보자.

#include <stdio.h>

void array_swap( char a[5], char b[5] )
{
    char temp[5];
    int i;

    printf("Swap before : a[%s][%p] b[%s][%p]\n", a, a, b, b);

    for( i=0; i<5; i++ )
    {
        temp[i] = a[i];
        a[i] = b[i];
        b[i] = temp[i];
    }

    printf("Swap after  : a[%s][%p] b[%s][%p]\n", a, a, b, b);

}

int main()
{
    char one[5] = "abcd";
    char two[5] = "1234";

    printf("Main before : one[%s][%p] two[%s][%p]\n", one, one, two, two);
    array_swap(one, two);
    printf("Main after  : one[%s][%p] two[%s][%p]\n", one, one, two, two);

    return 0;
}

위의 소스를 컴파일하여 실행하면 main 함수의 one, two 의 내용이 서로 바뀌어 있는 것을 알 수 있다. 분명 array_swap 함수의 인자인 a, b 는 main의 one, two 의 주소를 받는 것이다. 위 소스코드의 실행 결과는 다음과 같다.

Main before : one[abcd][0xbf990e82] two[1234][0xbf990e87]
Swap before : a[abcd][0xbf990e82] b[1234][0xbf990e87]
Swap after  : a[1234][0xbf990e82] b[abcd][0xbf990e87]
Main after  : one[1234][0xbf990e82] two[abcd][0xbf990e87]

그런데 사실 array_swap 함수의 a, b 가 주소를 받는 것이므로 a, b 뒤에 있는 [5] 의 5는 의미가 없다. 다시 말해서 a, b 는 array_swap을 호출할 때 넣어주는 배열의 주소만을 받는 것이다.

실제로 배열을 선언하면 그 배열의 주소는 바뀌지 않는다. 즉 다음과 같은 경우는 compile error 가 된다.

char c[100];
char *pc;
pc = c;      // OK!
c = pc;      // ERROR!

하지만, 함수의 인자로 선언된 배열은 그렇지 않다. 다음의 경우는 error 가 아니다.

void func( char c[] )
{
    char *pc;
    c = pc;   // NO ERROR!
}

결론은.. C언어에서 함수의 인자로 선언된 배열은 포인터로 동작한다.

이를 확인할 수 있는 방법이 있다.

위의 소스코드의 array_swap 에서 a, b 의 sizeof 는 4(32비트 OS기준) 이다. 이는 어떠한 크기의 배열을 받아도 변함이 없다.

즉, 함수 선언시 인자가 배열인 경우에도 call by value를 생각하여 배열 내부의 data가 모두 copy 되어 들어오는 게 아니라는 것이 중요하다.


댓글 없음:

댓글 쓰기