[C]va_copy()와 가변인자매크로
1️⃣ 가변인자함수
- C99이전부터 지원해준 가변인자함수는 [ft_printf]가변 인자 함수(variadic function)에 정리해 두었습니다.
2️⃣ va_copy
- 가변 인자로 선언된 변수를 복사하는 함수 입니다.(위치 지정자가 원본(ap)와 독립적)
(1) va_copy 간단한 예시
#include <stdarg.h>
#include <stdio.h>
void double_str_print(const char *format, ...)
{
va_list ap;
va_list ap_cp;
va_start(ap, format);
va_copy(ap_cp, ap);
{
printf("%s", va_arg(ap, char*));
printf("%s", va_arg(ap, char*));
printf("\n");
printf("%s", va_arg(ap_cp, char*));
printf("%s", va_arg(ap_cp, char*));
printf("\n");
}
va_end(ap);
va_end(ap_cp);
}
int main(void)
{
double_str_print("dd", "hello", " friend!");
}
hello friend!
hello friend!
va_copy 로 가변인자 리스트를 복사하면 원본(ap)에 구애받지 않고 사용할 수 있습니다.
(2) va_copy 주의 사항
- 하지만
복사시점 에 영향을 받기 때문에복사할때의 원본 가변인자 리스트의 위치 를 복사합니다. - 아래예시를 보면 원본(ap)을 한번 사용한 뒤 복사하면 복사본(ap_cp)는 두번째 가변인자 매개변수부터 복사됬음을 알 수 있습니다.
#include <stdarg.h>
#include <stdio.h>
void double_str_print(const char *format, ...)
{
va_list ap;
va_list ap_cp;
va_start(ap, format);
{
printf("%s", va_arg(ap, char*));
va_copy(ap_cp, ap); // ap를 한번 사용한 후 복사
printf("%s", va_arg(ap, char*));
printf("\n");
printf("%s", va_arg(ap_cp, char*));
printf("%s", va_arg(ap_cp, char*));
printf("\n");
}
va_end(ap);
va_end(ap_cp);
}
int main(void)
{
double_str_print("dd", "hello", " friend!", "nice!");
}
hello friend!
friend! nice!
3️⃣ 가변인자매크로
(1) 기존 매크로의 한계
#include <stdio.h>
#define TEST(a) printf(a);
int main(void)
{
TEST("Hello %s", "world!"); // 컴파일 오류
}
,(콤마)
가매개변수를 구분해주는 기호 로 쓰이기 때문에 매크로로써 복사가 불가능했습니다.- 매크로를 이용하여
가변인자 매개변수를 받는 함수 를 사용할때는 불편함이 있었습니다.ex) printf(“%s %d”, “hello”, 23);
- 하지만
C99
부터 가변인자 매크로를 지원합니다. - 사용법은 기존의 가변인자함수와 비슷하게
...
으로 매크로 인자를 받고__VA_ARGS__
로 호출할 수 있습니다.
#include <stdio.h<
#define TEST(...) printf(__VA_ARGS__);
int main(void)
{
TEST("Hello %s", "world!");
}
Hello world!
(2) 가변인자함수 #사용
__VA_ARGS__
는 기존 매크로 인자와 같이#
과 조합하여 사용할 수 있습니다.
#include <stdio.h>
#define TEST(...) printf(#__VA_ARGS__);
int main(void)
{
TEST("Hello \n", "world!");
}
< 서식지정자 사용할 경우(컴파일 오류) >
#include <stdio.h>
#define TEST(...) printf(#__VA_ARGS__);
int main(void)
{
TEST("Hello %s\n", "world!"); // %s를 추가해줌
}
- 하지만
#
기호를 조합한 가변인자 매크로는서식지정자 는 아직 적용이 안됩니다.
(3) 가변인자매크로 ##사용
- 아쉽게도
##
는가변인자매크로 와 조합하여 사용이 불가능했습니다.