본문 바로가기
코딩취미/C,C++

vsnprintf 의 기능과 가변인자(va_list) 리스트 사용 방법

by 브링블링 2023. 12. 6.
728x90

vsnprintf(buf, sizeof(buf), fmt, vl)의 기능

vsnprintf 함수는 형식 문자열과 가변 인자 리스트를 받아서 문자열을 생성하는 함수입니다. 이 함수는 printf와 비슷하지만, 출력 대상이 버퍼에 저장된다는 점이 다릅니다. 함수의 원형은 다음과 같습니다.

int vsnprintf(char *buf, size_t size, const char *fmt, va_list vl);
  • buf: 문자열을 저장할 버퍼의 포인터입니다.
  • size: 버퍼의 크기입니다. 버퍼에 저장할 수 있는 최대 문자 수를 나타냅니다.
  • fmt: 형식 문자열입니다. 이는 printf와 동일한 형식을 사용합니다.
  • vl: 가변 인자 리스트입니다. va_start 및 va_arg와 함께 사용됩니다.

vsnprintf는 fmt에 지정된 형식에 따라 문자열을 생성하고, 이를 버퍼 buf에 저장합니다. size는 버퍼의 크기로, 이 크기를 넘어가지 않도록 문자열을 생성합니다. 반환 값은 실제로 생성된 문자열의 길이입니다.

이 함수는 버퍼 오버플로우를 방지하기 위해 사용됩니다. 버퍼에 저장된 문자열이 지정한 크기를 초과하면 버퍼가 잘리고 널 종결 문자가 적절히 추가됩니다.

 

 

아래 코드에서 vsnprintf는 형식 문자열과 가변 인자를 받아서 buf에 문자열을 생성하고, 그 결과를 출력합니다.

#include <cstdio>
#include <cstdarg>

void exampleFunction(const char* fmt, ...) {
    char buf[100];  // 예제에서는 100바이트의 버퍼를 사용

    va_list args;
    va_start(args, fmt);

    int len = vsnprintf(buf, sizeof(buf), fmt, args);

    va_end(args);

    printf("Formatted string: %s\n", buf);
    printf("Length of the formatted string: %d\n", len);
}

int main() {
    exampleFunction("This is a %s with %d arguments: %f", "test", 3, 4.56);

    return 0;
}

 

va_start(args, fmt) 

va_start 매크로는 가변 인자 함수에서 가변 인자 리스트를 초기화하는 역할을 합니다. 가변 인자 함수는 함수에 전달된 가변 개수의 인자를 처리할 수 있는 함수로, 이때 va_start를 사용하여 인자 리스트를 초기화합니다.

va_start의 형태는 다음과 같습니다.

void va_start(va_list ap, last_arg);
  • ap: 가변 인자 리스트를 나타내는 va_list 타입의 포인터. 이는 함수 내에서 가변 인자에 접근하는 데 사용됩니다.
  • last_arg: 가변 인자 리스트의 이전에 나온 마지막 고정 인자. 가변 인자 리스트를 찾기 위해 필요합니다.

가변 인자 함수에서 va_start는 가변 인자 리스트를 초기화하므로 함수 내에서 va_arg 매크로를 사용하여 인자에 접근할 수 있습니다.

아래는 va_start의 간단한 예제 코드입니다.

 

exampleFunction은 가변 인자 함수로, va_start를 사용하여 가변 인자 리스트를 초기화하고, 그 후에 va_arg를 사용하여 인자에 접근합니다.

#include <cstdarg>
#include <iostream>

void exampleFunction(int count, ...) {
    va_list args;
    va_start(args, count);

    for (int i = 0; i < count; ++i) {
        int value = va_arg(args, int);
        std::cout << "Argument " << i + 1 << ": " << value << std::endl;
    }

    va_end(args);
}

int main() {
    exampleFunction(3, 10, 20, 30);

    return 0;
}
728x90

va_arg(args, int);

va_arg 매크로는 가변 인자 리스트에서 다음 가변 인자의 값을 반환하고, 리스트의 위치를 한 단계 앞으로 이동시키는 역할을 합니다. va_arg의 사용은 va_start로 초기화된 가변 인자 리스트에서만 가능합니다.

va_arg의 원형은 다음과 같습니다.

type va_arg(va_list ap, type);
  • ap: va_start로 초기화된 가변 인자 리스트입니다.
  • type: 반환할 값의 타입입니다.

va_arg를 호출할 때마다 가변 인자 리스트에서 type 타입의 값을 읽어오고, 다음 가변 인자로 이동합니다.

 

va_end(args)

va_end 매크로는 va_start를 통해 초기화된 가변 인자 리스트를 마무리하고 정리하는 역할을 합니다. va_end를 호출하면 더 이상 va_arg로 인자에 접근할 수 없으며, 해당 가변 인자 리스트의 사용이 종료됩니다.

va_end의 원형은 다음과 같습니다.

void va_end(va_list ap);

va_end(args)va_start로 초기화된 가변 인자 리스트 args를 마무리합니다. 함수에서 가변 인자 리스트를 더 이상 사용하지 않을 때 va_end를 호출하는 것은 좋은 프로그래밍 습관입니다.

 

va_list 사용 목적

va_list는 C 프로그래밍에서 가변 인자 함수(variable-argument function)를 구현할 때 사용되는 매크로입니다. 가변 인자 함수는 인자의 개수가 고정되지 않은 함수를 말하며, 주로 printf, scanf 등이 대표적인 가변 인자 함수입니다.

가변 인자 함수를 정의할 때 va_list을 사용하는 이유는 다음과 같습니다:

  1. 가변 개수의 인자 처리: 함수에 얼마나 많은 인자가 전달될지 미리 알 수 없을 때 사용됩니다. va_list를 사용하면 함수가 실행될 때 전달된 인자의 개수에 따라 동적으로 처리할 수 있습니다.
  2. 타입 변환: 가변 인자 함수에서는 다양한 타입의 인자를 받을 수 있어야 합니다. va_list을 사용하면 가변 인자 리스트에서 다양한 타입의 값을 가져올 수 있습니다.

가변 인자 함수를 작성하는 일반적인 단계는 다음과 같습니다:

  1. 가변 인자 리스트 선언: 함수의 파라미터 리스트에 ...을 사용하여 가변 인자를 선언합니다.
  2. 가변 인자 리스트 초기화: va_start를 사용하여 va_list를 초기화합니다. va_start는 가변 인자 리스트를 참조할 수 있도록 설정합니다.
  3. 가변 인자 읽기: va_arg를 사용하여 가변 인자 값을 읽습니다. va_arg는 해당 타입의 값을 반환하고, 가변 인자 리스트를 다음 인자로 이동시킵니다.
  4. 가변 인자 리스트 마무리: 작업이 끝나면 va_end를 사용하여 가변 인자 리스트를 마무리합니다.
728x90