제가 Microsoft Windows 프로그래밍만 해 오다가 Linux 프로그래밍을 하면서 느끼는 편리함 중에 하나는 중요 에러가 발생했거나 아리까리한 문제가 발생했다면 주저없이 프로그램을 종료할 수 있다는 점입니다.

중요 에러야 당연히 종료해야 겠지만 아리까리한 경우도 어찌어찌 힘들게 살리는 코드를 역시 힘들게 만들어 넣어서 어설프게 실행되는 것 보다는 그냥 종료해 버리고 새로 실행하도록 하는 것이 좋더군요. 이렇게 처리하는 방법이 의외로 시운 것에 놀랬습니다.

그러다 보니 exit() 함수를 자주 사용하는데요, 또한 디버깅을 위해 에러 문자열을 출력해줍니다. 그러니까 이렇게 하는 거죠.

printf( "%sn", msg);   
exit( 0);

그러나 너무 자주 사용하는 경우라 함수로 만들었습니다.

void showmsg_and_exit( char *msg)
{
  printf( "%sn", msg);   
  exit( 0);
}

int   main( int argc, char **argv)
{
   showmsg_and_exit( "에러가 발생해서 종료합니다.");
   printf( "여기는 실행 안됩니다.n");
   
   return 0;
}

그러나 아쉬운 것이 인수를 전달하지 못한다는 점입니다.

가변 인자, va_list

printf() 가 포맷 문자열에 맞추어서 다양한 인수를 전달 받는 것처럼 내가 만든 함수도 다양한 인수를 받게할 수 없을까하는 생각을 갖을 수 있는데요, 그게 바로 va_list 입니다.

우선 제가 애용하는 코드를 보시겠습니다.

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

static char     *__bar  = "---------------------------------------------------------n";   

void  printx( const char *format, ...)
{
   va_list   arg;
   int       count;

   printf( "%sERR: ", __bar);

   va_start( arg, format);
   count = vprintf( format, arg);
   va_end( arg);  
   
   printf( "n%s", __bar);
   exit( -1);
}

int   main( int argc, char **argv)
{
   printx( "에러가 발생해서 종료합니다. 에러코드= %d", 1234);
   printf( "여기는 실행 안됩니다.n");
   
   return 0;
}

실행하면 아래와 같이 출력됩니다.

]$ ./sample
---------------------------------------------------------
ERR: 에러가 발생해서 종료합니다. 에러코드= 1234
---------------------------------------------------------

이렇게 va_list 를 사용하시면 printf() 함수처럼 가변 인수를 받는 함수를 만드실 수 있습니다.

또 다른 예

제가 보여드린 예에서는 vprintf()를 사용하여 printf()를 수행하듯 처리했지만 아래와 같이 포맷 문자열 없이도 사용이 가능합니다. 아래의 예는 숫자 여러 개를 인수로 받아 평균 값을 구하는 예입니다.

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

int   average( int count, ...)
{
   va_list   arg;
   int       sum;
   int       ndx;
                 
   sum   = 0;                 
   va_start( arg, count);

   for ( ndx= 0; ndx < count; ndx++)
      sum += va_arg( arg, int);   

   va_end( arg);  
   return sum / count;
}

int   main( int argc, char **argv)
{
   printf( "%dn", average( 5, 1, 2, 3, 4, 5));
   printf( "%dn", average( 3, 1, 2, 3));
   
   return 0;
}

어떻습니까? 항상 함수에서 지정된 인수만 받아야 하지만 va_list를 이용하면 간변 인수를 받을 수 있습니다.

 

태그: *gcc *가변인수 *va_list *C언어 *초보