[42서울] 가변인자 함수

tamagoyakii·2022년 3월 23일
0

42seoul

목록 보기
1/19
post-thumbnail

오랜만에 포스팅이다. 갑자기 C언어다. 프로젝트를 끝내고 이제 42서울 과제들을 차차 풀어볼까 한다. 블랙홀도 얼마 남지 않았고...😢 오늘은 ft_printf를 풀기에 앞서 가변인자 함수에 대해 써보려고 한다.

🌷 가변인자 함수

함수에 들어가는 인자의 개수가 변하는 것을 가변인자(가변인수, variable argument)라고 한다. 가변인자 함수는 하나의 함수 프로토타입에 여러 인자를 받아 사용하고싶을 때 필요하다. 가변인자는 포인터의 작용으로 이루어지는데, 인자를 스택에 쌓아두었다가 하나씩 빼서 사용하는 형식으로 작동한다.

✅ 헤더 파일

#include <stdarg.h>

stdarg 헤더파일에는 1개의 타입과 4개의 메크로 함수가 정의되어 있다. 이에 대한 내용은 밑에서 설명하겠다.

✅ 가변인자 함수의 정의

반환값자료형 함수이름(자료형 고정매개변수, ...)

int	ft_printf(const char *format, ...)

인자의 개수를 정확하게 알지 못하기 때문에 위와 같이 ... 으로 표기한다. 가변인자 함수를 사용할때에는 최소 1개의 고정매개변수가 있어야 하며, ... 은 파라미터의 가장 마지막 순서에 위치해야한다.

✅ va_list

va_list ap;

가변 인자 목록이다. 가변 인자의 메모리 주소를 저장하는 포인터라고 생각하면 된다. 위의 형식으로 선언하여 사용한다. 여기서 ap 는 “argument pointer”의 약자로, 인자 목록에 접근하는 포인터라는 뜻이다.

✅ Macro Functions

💡 매크로 함수란?
C언어에서는 #define 선행처리 지시문에 인수로 함수의 정의를 전달함으로써, 함수처럼 동작하는 매크로를 만들 수 있다. 이러한 매크로를 함수 같은 매크로(function-like macro) 또는 매크로 함수라고 부른다. 매크로 함수는 일반 함수와는 달리 단순 치환만을 해주므로, 일반 함수와 완전히 똑같은 방식으로 동작하지는 않는다. 일반 함수는 인수를 프로그램이 실행 중일 때 전달받지만, 매크로 함수는 인수를 컴파일 이전에 미리 치환하기 때문이다. 매크로 함수가 일반 함수처럼 작동하기 위해서는 아래의 사항에 주의하여 작성해야한다.

  1. 매크로 함수의 전체를 괄호(())로 감싸야 한다.
  2. 매크로 함수의 인수들도 각각 괄호로 감싸야 한다.
  3. 매크로 함수를 호출할 때에는 증감 연산자(++, --)나 복합 대입 연산자 등은 사용하지 않는 것이 좋다.

1. va_start(ap, v)

가변 인자를 가져올 수 있도록 포인터를 설정한다. 여기서 v는 고정매개변수이다.

2. va_arg(ap, 자료형)

가변 인자 포인터에서 특정 자료형 크기만큼 값을 가져온 뒤, 자료형 크기만큼 순방향으로 이동한다.

3. va_copy(va_list dest, va_list src)

가변 인자 리스트를 복사한다. 복사시점에 영향을 받기 때문에 복사할때의 src리스트의 위치를 복사한다.

4. va_end(ap)

가변 인자 처리가 끝났을 때 포인터를 NULL로 초기화 한다.

#include <stdio.h>
#include <stdarg.h>    // va_list, va_start, va_arg, va_end가 정의된 헤더 파일

void printNumbers(int args, ...)    // 가변 인자의 개수를 받음, ...로 가변 인자 설정
{
    va_list ap;    // 가변 인자 목록 포인터

    va_start(ap, args);    // 가변 인자 목록 포인터 설정
    for (int i = 0; i < args; i++)    // 가변 인자 개수만큼 반복
    {
        int num = va_arg(ap, int);    // int 크기만큼 가변 인자 목록 포인터에서 값을 가져옴
                                      // ap를 int 크기만큼 순방향으로 이동
        printf("%d ", num);           // 가변 인자 값 출력
    }
    va_end(ap);    // 가변 인자 목록 포인터를 NULL로 초기화

    printf("\n");    // 줄바꿈
}

int main()
{
    printNumbers(1, 10);                // 인수 개수 1개
    printNumbers(2, 10, 20);            // 인수 개수 2개
    printNumbers(3, 10, 20, 30);        // 인수 개수 3개
    printNumbers(4, 10, 20, 30, 40);    // 인수 개수 4개

    return 0;
}

🌷 참고자료

https://dojang.io/mod/page/view.php?id=577
http://www.tcpschool.com/c/c_prepro_macroFunc

0개의 댓글