[C]va_copy()와 가변인자매크로



1️⃣ 가변인자함수


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 &lt;stdio.h&lt;

#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를 추가해줌
}

va_mecro_badcase

  • 하지만 #기호를 조합한 가변인자 매크로서식지정자는 아직 적용이 안됩니다.

(3) 가변인자매크로 ##사용

  • 아쉽게도 ##가변인자매크로와 조합하여 사용이 불가능했습니다.

va_mecro_badcase




© 2021.02. by kirim

Powered by kkrim