2. 가변인자 (Variadic Arguments)

가만보면 printf 라는 함수는 인자를 1개만 넣어도 되고, 2개만 넣어도 되고, 3개, 4개 그 이상을 넣어도 문제없이 돌아간다. 이것을 가능하게 하는 가변인자(Variadic Arguments)에 대해 정리해보았다.

1. Printf() 함수의 매개변수...?

printf 함수를 재구현하는 ft_printf 프로젝트를 시작하면 서 들게 된 의문이 있다. printf를 사용하면서 우리는 자연스럽게 printf("%d * %d = %d", 3, 5, 3*5)라고 쓰고 있다. 가만보면 printf라는 함수는 인자를 1개만 넣어도 되고, 2개만 넣어도 되고, 3개, 4개 그 이상을 넣어도 문제없이 돌아간다.

이것을 가능하게 하는 가변 인자에 대해 정리해보았다.

2. 가변인자란?

아래 sum 함수의 두 번째 인자로 사용되는 ...가변 인자 혹은 가변 파라미터라고 불리는 것이다. 매개변수로 아무것도 넘겨주지 않을 수도 있고, 혹은 여러 개를 넘겨줄 수도 있다. 이러한 매크로는 함수가 고정된 수의 필수 인수에 가변 수의 선택적 인수가 붙은 형식을 사용한다고 가정한다.

    #include <stdio.h>
    #include <stdarg.h>

    int sum(int count, ...)
    {
        int res = 0;
        va_list ap;
        int i;

        va_start(ap, count);

        for(i=0; i<count; i++)
            res += va_arg(ap, int);

        va_end(ap);

        return res;
    }

    int main()
    {
        printf("%d\n", sum(10, 1,2,3,4,5,6,7,8,9,10));

        return 0;
    }

    출력 결과 >> 55

3. 각 매크로에 대한 설명

va_list

각 가변 인자의 시작 주소를 가리킬 포인터이다.

va_start

    void va_start(va_list ap, variable_name);

va_list로 만들어진 포인터에게 가변인자 중 첫 번째 선택적 인수(variable_name)의 주소를 가르쳐주는 중요한 매크로이다. va_arg(), va_copy(), va_end()에 대한 후속 호출에 대해 ap 포인터를 초기화한다.

  • ap: va_list 로 만든 포인터가 담긴다.

  • variable_name: 인수 목록의 첫 번째 인자 바로 앞에 오는 필수 매개 변수의 이름. 즉, 마지막 고정된 필수 인수가 담긴다.

va_copy

    void va_copy(va_list dest, va_list src);

va_start()를 dest에 적용한 후 src의 현재 상태에 도달하는 데 이전에 사용된 것과 동일한 순서로 va_arg()를 사용한 경우와 같이 destsrc의 사본으로 초기화한다. va_copy() 또는 va_start()는 동일한 dest에 대한 va_end()의 중간 호출 없이 dest를 다시 초기화하도록 호출해야 한다.

va_arg

    var_type va_arg(va_list ap, var_type);

ap로 지정된 위치에서 지정된 var_type 값을 검색하고 리스트에서 다음 인수를 가리키도록 ap 를 증가 시켜 다음 인수가 시작 되는 위치를 결정한다. 즉, 특정 가변인자를 가리키고 있는 va_list의 포인터를 다음 가변인자로 이동시켜 주는 매크로이다.

  • ap: va_list로 만든 포인터가 담긴다.

  • var_type: intlong, double과 같은 타입 이름이 담긴다.

var_type을 설정할 때 char, short 의 경우에는 int로 대신 쓰고, flaot의 경우에는 double로 대신 쓴 이후 형 변환을 해주어야 한다. ex) char ch = (char) va_arg(ap, int);

va_end

    void va_end(va_list arg_ptr);

모든 인수가 검색 된 후 va_end 는 포인터를 NULL로 다시 설정 한다. 즉, 사용한 가변인자 변수를 끝낼때 사용.

4. 반환값

va_arg() 함수는 현재 인수를 리턴한다. va_copy(), va_end(), va_start() 함수는 값을 리턴하지 않는다.

5. 참고

C언어 가변인자(가변파라미터)를 사용해보자

va_arg, va_copy, va_end, va_start

Last updated