Language/C++ 11

[C++11] 가변인자(Variable Argument)를 이용한 Logger 만들기

마탁이 2021. 2. 28. 18:19

1. 가변인자란?

 - 변수의 개수가 상황마다 변할 수 있는 인자.

 - 대표적인 예로 printf()와 scanf()

 

2. 가변인자를 사용하기 위한 함수

 - va_start(var_list, lastfix)

  > Stack 상의 첫 가변인수의 위치를 구해 va_list 형에 대입한다. 함수가 호출되기 전에 선언되어 있어야 한다.

  > lastfix는 고정인수를 뜻한다. 고정인수는 가변인수의 시작번지를 찾기 위한 역할을 한다.

    (고정인수의 다음이 가변인수의 시작번지)

 

 - va_arg(va_list, type)

  > 가변 인수를 읽는 함수

  > 첫 번째 인수는 va_start가 사용한 ap와 동일한 변수이고, ap가 가리키는 번지의 데이터를 가변인수로 읽는다.

  > 두 번째 인수는 type은 가변인수의 데이터 형을 나타낸다. (데이터형에 따라 읽고 Return)

   * type의 인수로는 char, float은 사용될 수 없다.

 

 - va_end(va_list)

  > 가변 인수를 다 읽은 후 함수가 정상적으로 Return되도록 도와준다.

  > va_end가 호출되면 ap가 변경되로 va_start를 호출하지 않고는 가변 인수를 다시 읽을 수 없도록 한다.

 

 - 예제

#include <iostream>
#include <cstdarg>

void PrintNums(int argSize, ...)
{
    va_list ap;

    va_start(ap, argSize);
    for(int i = 0; i < argSize; i++)
    {
        int n = va_arg(ap, int);
        printf("args %d : %d\n", argSize, n);
    }
    va_end(ap);
    std::cout<<std::endl;
}

int main()
{
    PrintNums(2,1,2);
    PrintNums(4,1,2,3,4);

    return 0;
}

<가변인수 예제 코드 결과>

 

3. 가변인수 매크로

 - 가변인수 '...'을 매크로로 넘기는 방법 (__VA__ARGS__, ##__VA_ARGS__)

 - ##__VA_ARGS는 가변인수가 한 개도 없을 때 컴파일러 에러를 해결하기 위한 방법.(','를 삭제)

 

 

4. file name, line, function name 을 출력하는 Logger

#include <iostream>
#include <sstream>
#include <cstdarg>
#include "string.h"
#include "pthread.h"

#include <cstdio>

#define LOG_MAIN_CONSOLE(fmt, ...) LOG_CONSOLE("mainProcess", __FILE__, __LINE__, __FUNCTION__,  fmt, ##__VA_ARGS__)
void LOG_CONSOLE(const char *procName, const char *fileName, const int line, const char *funcName, const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    printf("[%s][FILENAME :%s, LINE : %d, FUNC : %s] ", procName, fileName, line, funcName);
    vprintf(fmt, ap);
    va_end(ap);
}

int main()
{
    int a = 54;


    LOG_MAIN_CONSOLE("Hi %d", a);
    

    return 0;
}