본문 바로가기

공부기록/42 Seoul

[ft_printf] 02 가변인자(variable argument) 에 대하여

man 3 stdarg 명령으로 stdarg에 관한 메뉴얼을 읽어봤다.

다음은 메뉴얼 페이지에 있는 각 함수의 원형이다.

#include <stdarg.h>

void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_copy(va_list dest, va_list src);
void va_end(va_list ap);

va_list 각 가변 인자의 시작 주소를 가리킬 포인터. 내부적으로는 char * 로 정의되어 있다.

va_start() : va_list로 만들어진 포인터에게 첫 번째 가변인자의 주소를 가르쳐준다.

va_arg() : 특정 가변인자를 가리키고 있는 va_list의 포인터를 다음 가변인자로 이동시켜준다.

va_arg는 type으로 int 보다 작은 자료형을 받을 수 없다고 한다.
관련 링크는 -> https://stackoverflow.com/questions/28054194/char-type-in-va-arg#:~:text=So%20a%20variadic%20function%20can,all%20functions%20behaved%20this%20way

va_copy() : va_start()에 의해 초기화 되었던 이전의 가변인자 리스트가 복사된다. dest 는 va_start()에 의해 초기화되지 않은 변수여야 한다.

 

그리고 가변인자를 잘 이해할 수 있는 예제코드

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

void foo(char *fmt, ...)
{
        va_list ap;
        va_list ap2;
        int d, i;
        char c, *s;

        i = 0;
        va_start(ap, fmt);
        va_copy(ap2, ap);
        while (fmt[i] != '\0')
                switch(fmt[i++]) {
                case 's':                       /* string */
                        s = va_arg(ap, char *);
                        printf("string %s\n", s);
                        break;
                case 'd':                       /* int */
                        d = va_arg(ap, int);
                        printf("int %d\n", d);
                        break;
                case 'c':                       /* char */
                        /* Note: char is promoted to int. */
                        c = va_arg(ap, int);
                        printf("char %c\n", c);
                        break;
                }
        va_end(ap);
        //...
        /* use ap2 to iterate over the arguments again */
        /* we don't have to use va_start() here */
        i = 0;
        while (fmt[i] != '\0')
                switch(fmt[i++]) {
                case 's':                       /* string */
                        s = va_arg(ap2, char *);
                        printf("string %s\n", s);
                        break;
                case 'd':                       /* int */
                        d = va_arg(ap2, int);
                        printf("int %d\n", d);
                        break;
                case 'c':                       /* char */
                        /* Note: char is promoted to int. */
                        c = va_arg(ap2, int);
                        printf("char %c\n", c);
                        break;
                }
        va_end(ap2);
}

int main()
{
    foo("sddcc", "always", 4, 3, 99, 'p');
    return 0;
}

 

 


참고