Type Here to Get Search Results !

C언어 가변인자 함수의 사용법:va_start:va_arg:va_list:va_end:vsprintf:vsnprintf

이 글에서는 C언어의 가변인자에 대해서 알아보고 이를 사용한 예제를 설명합니다. 

  • 가변인자란?
  • 가변인자 사용 예제 3가지
C언어 가변인자 사용하기 썸네일


가변인자란?


C 언어에서 가변인자(variable arguments)란 함수의 매개변수(parameter)로 개수가 정해져 있지 않은 인자(argument)들을 받을 수 있도록 하는 기능입니다. 가변인자를 사용하면 함수를 호출할 때 필요한 인자의 개수가 고정되지 않아도 되므로, 다양한 상황에서 유연하게 사용할 수 있습니다.

가변인자를 사용하기 위해서는 stdarg.h 헤더 파일을 포함시켜야 합니다. 이 헤더 파일에는 가변인자를 다루기 위한 매크로와 함수들이 정의되어 있습니다.

가변인자 함수의 선언 방법은 다음과 같습니다.

int func_name(int arg1, ...);

마지막 인자(parameter)에 ...을 붙여 가변인자임을 명시합니다. 가변인자를 받는 함수 내부에서는 va_list, va_start, va_arg, va_end 등의 매크로와 함수를 사용하여 가변인자를 처리합니다.


va_list: 가변인자 목록을 가리키는 포인터 타입입니다.

va_start: 가변인자 처리를 시작할 때, 가변인자 목록의 첫 번째 인자의 주소와 va_list 타입의 포인터를 연결합니다.

va_arg: 가변인자 목록에서 인자를 하나씩 가져옵니다. 가져온 인자의 타입은 va_arg의 두 번째 인자로 지정합니다.

va_end: 가변인자 처리가 끝났을 때, 가변인자 목록 처리를 종료합니다.

가변인자 사용 예제 3가지


기본 예제 

int 변수들을 가변인자로 받고, 1개면 "hello %d\n"을 출력하고, 두 개면 "hello %d, %d\n"을 출력하는 함수를 예제로 작성해 보겠습니다.  

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

void print_hello(int count, ...)
{
    va_list args;
    va_start(args, count);
    
    if (count == 1) {
        int arg1 = va_arg(args, int);
        printf("hello %d\n", arg1);
    }
    else if (count == 2) {
        int arg1 = va_arg(args, int);
        int arg2 = va_arg(args, int);
        printf("hello %d, %d\n", arg1, arg2);
    }
    
    va_end(args);
}
위의 코드에서는 가변인자를 처리하기 위해 va_list, va_start, va_arg, va_end 매크로를 사용하였습니다. 함수 호출 시 첫 번째 인자로 가변인자의 개수를 전달하고, 두 번째 인자부터는 가변인자를 순서대로 전달합니다.

예를 들어, 아래와 같이 함수를 호출하면 결과는 다음과 같습니다.
int main()
{
    print_hello(1, 10); // "hello 10" 출력
    print_hello(2, 10, 20); // "hello 10, 20" 출력
    
    return 0;
}

응용 예제

buffer를 인자로 받고 char* 여러 개를 가변인자로 받아서 입력된 모든 char*를 buffer에 복사하는 함수를 작성해 보겠습니다.  

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

void copy_strings(char* buffer, int buffer_size, ...)
{
    va_list args;
    va_start(args, buffer_size);
    
    char* str;
    int length, copied = 0;
    
    while ((str = va_arg(args, char*)) != NULL && copied < buffer_size - 1) {
        length = strlen(str);
        if (copied + length >= buffer_size) {
            break;
        }
        strcpy(buffer + copied, str);
        copied += length;
    }
    buffer[copied] = '\0';
    
    va_end(args);
}
위의 코드에서는 가변인자를 처리하기 위해 va_list, va_start, va_arg, va_end 매크로를 사용하였습니다. 함수 호출 시 첫 번째 인자로 버퍼 포인터와 버퍼의 크기를 전달하고, 두 번째 인자부터는 가변인자로 문자열을 순서대로 전달합니다. 문자열은 NULL 포인터로 구분합니다.

위의 코드에서는 입력된 문자열을 순서대로 버퍼에 복사하는데, 버퍼의 크기를 초과하지 않도록 주의합니다. 만약 버퍼의 크기를 초과하면 복사를 중단하고 루프를 빠져나가며, 마지막으로 버퍼의 끝에 널 문자('\0')를 추가하여 문자열의 끝을 표시합니다.

예를 들어, 아래와 같이 함수를 호출하면 결과는 다음과 같습니다.
int main()
{
    char buffer[100];
    copy_strings(buffer, sizeof(buffer), "hello", ", ", "world", "!", NULL);
    printf("%s\n", buffer); // "hello, world!"
    
    return 0;
}

vsprintf를 통한 my_printf 예제

vsprintf 함수는 가변인자를 받아서 서식화된 문자열을 생성하는 함수입니다. vsprintf 함수는 sprintf 함수와 비슷하지만, 가변인자 대신 va_list 타입의 인자를 받아들입니다. 이 함수는 생성된 문자열을 지정된 버퍼에 저장합니다.


아래의 예제 코드는 vsprintf 함수를 사용하여 입력된 서식화된 문자열과 가변인자를 이용하여 새로운 문자열을 생성하고 이를 버퍼에 저장하는 예제입니다.

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

void my_printf(char* buffer, int buffer_size, const char* format, ...)
{
    va_list args;
    va_start(args, format);
    vsprintf(buffer, format, args);
    va_end(args);
}

int main()
{
    char buffer[100];
    my_printf(buffer, sizeof(buffer), "Hello %s, your score is %d!", "John", 80);
    printf("%s\n", buffer); // "Hello John, your score is 80!"
    return 0;
}
위의 코드에서는 my_printf 함수를 사용하여 입력된 서식화된 문자열과 가변인자를 이용하여 새로운 문자열을 생성하고 이를 버퍼에 저장하였습니다. 이때 vsprintf 함수를 사용하여 새로운 문자열을 생성하였습니다.

함수 호출 시 첫 번째 인자로는 버퍼 포인터와 버퍼의 크기를 전달하고, 두 번째 인자부터는 서식화된 문자열과 가변인자를 전달합니다. vsprintf 함수는 생성된 문자열을 지정된 버퍼에 저장합니다.

위의 코드에서는 my_printf 함수를 호출하여 새로운 문자열을 생성하고 버퍼에 저장하였습니다. 이후 printf 함수를 사용하여 버퍼에 저장된 문자열을 출력하였습니다.