c언어에서 printf
와 같이 매개변수의 갯수가 정해지지 않는 함수가 있다. 이렇게 함수에 들어가는 인수의 갯수가 변하는 것을 가변인자(가변 인수, variable argument)라고 한다.
<stdarg.h>
...
을 붙여 매개변수의 개수가 정해지지 않았다는 표시를 해준다.printf
함수의 경우,printf("My name is %s. Her name is %s. His name is %s\n", name1, name2, name3);
" "
로 묶여진 첫번째 문자열 인자가 필수 인자가 되는 것이고, name1
부터 name3
가 가변인자이다. 일반적으로 필수 인자에서 가변인자를 몇 개 받았는지 명시하여 정지신호를 찾을 수 있게 해준다. printf에서는 서식지정자의 개수로 알 수 있다. va_list
: 가변인자 목록 포인터, 가변인자의 메모리 주소를 저장한다.va_start
: 가변인자를 가져올 수 있도록 포인터를 초기화한다. 쉽게 말해서, 가변인자를 가져올 수 있도록 가변인자 시작 주소를 포인터에 담는다.va_arg
: 가변인자포인터에서 특정 자료형 크기만큼 값을 가져온다.(*값을 가져온 뒤 자료형 크기만큼 포인터 이동)va_end
: 가변인자 처리가 끝났을 때, NULL
로 포인터를 초기화 해준다.코드 예시
#include <stdio.h>
#include <stdarg.h> // 가변인자 매크로가 정의된 헤더 파일
void ft_printNumbers(int args, ...) // ...로 가변 인자 설정
{
va_list ap; // 가변 인자 목록 포인터
int i = 0;
va_start(ap, args); // 가변 인자 목록 포인터와 가변인자와 연결
while (i < args) // 가변 인자 개수만큼 반복
{
int number = va_arg(ap, int); // int 크기만큼 값을 가져온 뒤,
// ap를 int 크기만큼 이동
printf("%d ", number); // 가변 인자 값 출력
i++;
}
va_end(ap); // 가변 인자 목록 포인터를 NULL로 초기화
}
int main()
{
ft_printNumbers(5, 10, 20, 30, 40, 50); // 필수인자로 가변인자의 개수를 받음
return (0);
}
각 자료형에 맞게 분기해주면 된다.
코드 예시
#include <stdio.h>
#include <stdarg.h>
void ft_printMultiple(char *types, ...) // 가변 인자의 자료형을 필수인자로 받음
{
va_list ap; // 가변 인자 목록 포인터
int i = 0;
va_start(ap, types); // types 문자열에서 문자 개수를 구해서 가변 인자 포인터 설정
while (types[i] != '\0') // 가변 인자 자료형이 없을 때까지 반복
{
if (types[i] == 'i') // 가변 인자 자료형으로 분기
{
printf("%d ", va_arg(ap, int));
}
else if (types[i] == 'd')
{
printf("%f ", va_arg(ap, double));
}
else if (types[i] == 'c')
{
printf("%c ", va_arg(ap, int)); // GCC에서 char형 문자일 때 int를 사용해야 함!
}
else if (types[i] == 's')
{
printf("%s ", va_arg(ap, char *));
}
else
return ;
i++;
}
va_end(ap); // 가변 인자 포인터를 NULL로 초기화
}
int main()
{
ft_printMultiple("sicd", "Hello!", 2022, 'a', 3.30); // 필수인자로 가변인자의 개수와 자료형을 받음
return (0);
}
피신을 준비할 때 참 많이 보면서 공부했던 사이트인데, 역시 없는 게 없었다...!👍
c언어 코딩도장 - 66.1 가변인자 함수 만들기
c언어 코딩도장 - 66.2 자료형이 다른 가변 인자 함수 만들기