va_start(3) / va_arg(3) / va_end(3)

#include <stdarg.h>

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

 

함수를 구현할 때에, 파라미터의 갯수가 몇 개가 올지 모르는 경우가 종종 발생합니다. 이와 같이 동적 파라미터 함수는 단순히 파라미터에 ...을 붙인다고 될 문제는 아닙니다.  약간 복잡하지만 동적 파라미터 함수를 구현하는 방법에 대해서 알아보겠습니다.

 

동적 파라미터 함수를 만들 때에는 3가지에 대해서 정의가 되어야 합니다.

  1. 고정으로 1개 이상의 파라미터는 정해져야 합니다.

  2. 파라미터의 갯수가 몇 개인지를 알 수 있는 방법 제공

  3. 각 파라미터의 type이 무엇인지를 알 수 있는 방법 제공

 

 

예 1)

double sum(int count, ...); 

이 함수는 count 갯수 만큼의 dobule형의 데이터를 파라미터로 넘겨서 모두 더하는 함수라고 가정합니다.

    파라미터의 갯수를 아는 방법: count
    파라미터의 type을 아는 방법: 모든 데이터는 double

double sum(int count, ...)
{
    int idx;
    va_list args;
    double sum_data = 0.0;

    /* count paramter 뒤부터 동적 parameter가 시작되는 설정합니다. */
    va_start(args, count);

    for(idx = 0; idx < count; idx++) {
        /* 
        * 파라미터를 한개씩 읽어서 데이터를 double로 type casting하고 
                * 다음 parameter로  pointer를 이동시킵니다.
        */

        sum_data += va_arg(args, double);
    }
    /* 동적 parameter의 설정을 해제합니다. */
    va_end(args);

    return sum;
}

사용할 때는....

double  total;

......

total = sum(5, 123.4, 2.0, 4, 5, 6);

 

 

예2).

char * concat(char *dest, ...); 

이 함수는 뒤에 이어지는 파라미터의 문자열을 붙여서 dest에 저장하는 함수라고 가정을 합니다.

    파라미터의 갯수를 아는 방법 : 마지막 데이터가 NULL이면 더 이상 데이터가 없음
    파라미터의 type을 아는 방법 : 모든 데이터 type이 문자열 

char * concat(char *dest, ...)
{
    int idx;
    va_list args;
    const char *data; 
    
    dest[0] = 0x00;

    /* dest paramter 뒤부터 동적 parameter가 시작되는 설정을 합니다. */
    va_start(args, dest);

    while(1) {
        data = va_arg(args, const char *);
        
        if(data == NULL) {
            break;
        }
        strcat(dest, data);
    }
    /* 동적 parameter의 설정을 해제합니다. */
    va_end(args);

    return dest;
}

사용할 때에는

char buf[1024];

...

concat(buf, "My", " ", "friends", NULL);
printf("%s\n", buf);

----------------------------------------
결과
My frineds

 

동적 파라미터의 대표적인 함수는 printf(3)함수가 있습니다. 

int printf(const char *format, ...);

이 함수를 보면

     파라미터의 갯수를 아는 방법 : %%를 제외한 %의 갯수

     파라미터의 type을 아는 방법 : %뒤에 오는 s / d /c / f ...

로 판단합니다.

 

 

정리하면,

동적 파라미터의 함수를 구현하려면,

1. 고정된 파라미터는 반드시 하나 이상 존재해야 합니다. 
       그래야 ...의 시작 위치가 그 파라미터 뒤라고 va_start()로 지정할 수 있기 때문입니다.

2. ... parameter로 넘어 온 데이터가 무슨 type인지 정해져 있거나 알 수 있어야 합니다.
      위의 dobule sum( )은 double type으로 정해놓고 구현하였습니다.
      execl( )함수는 ... 부분이 const char *라고 이미 정해놓고 구현한 경우입니다.
      printf( )함수는 format 부분에 %s는 const char * 형 이고 %d는 int 형이다 라는 것을 
            해석할 수 있게 약속해놨습니다.


3. ...의 갯수는 몇 개인지를 알 방법을 정해야 합니다.
      위의 dobule sum( )은 첫번째 파라미터가 ...이 몇개의 파라미터인지를 알 수 있게 했습니다.
      execl( ) 함수는 NULL을 만나면 파라미터의 끝이라는 것을 규칙으로 정했습니다.
      printf( ) 함수는 %s는 나 %*.*s등의 표기를 보고 파라미터 갯수를 알 수 있습니다.
      fcntl( ) 함수는 두번째 파라미터가 F_GETxx 이면 2개 
                             F_SETxx이면 3개의 파라미터로 인식합니다.

 


 

see also :  v...printf(3) 활용 : printf(3)같은 동적 파라미터 함수 만들기

 

 

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

Tag , ,

댓글을 달아 주세요