오랜만에 포스팅이다. 갑자기 C언어다. 프로젝트를 끝내고 이제 42서울 과제들을 차차 풀어볼까 한다. 블랙홀도 얼마 남지 않았고...😢 오늘은 ft_printf
를 풀기에 앞서 가변인자 함수에 대해 써보려고 한다.
함수에 들어가는 인자의 개수가 변하는 것을 가변인자(가변인수, variable argument)라고 한다. 가변인자 함수는 하나의 함수 프로토타입에 여러 인자를 받아 사용하고싶을 때 필요하다. 가변인자는 포인터의 작용으로 이루어지는데, 인자를 스택에 쌓아두었다가 하나씩 빼서 사용하는 형식으로 작동한다.
#include <stdarg.h>
stdarg
헤더파일에는 1개의 타입과 4개의 메크로 함수가 정의되어 있다. 이에 대한 내용은 밑에서 설명하겠다.
반환값자료형 함수이름(자료형 고정매개변수, ...)
int ft_printf(const char *format, ...)
인자의 개수를 정확하게 알지 못하기 때문에 위와 같이 ...
으로 표기한다. 가변인자 함수를 사용할때에는 최소 1개의 고정매개변수가 있어야 하며, ...
은 파라미터의 가장 마지막 순서에 위치해야한다.
va_list ap;
가변 인자 목록이다. 가변 인자의 메모리 주소를 저장하는 포인터라고 생각하면 된다. 위의 형식으로 선언하여 사용한다. 여기서 ap
는 “argument pointer”의 약자로, 인자 목록에 접근하는 포인터라는 뜻이다.
💡 매크로 함수란?
C언어에서는#define
선행처리 지시문에 인수로 함수의 정의를 전달함으로써, 함수처럼 동작하는 매크로를 만들 수 있다. 이러한 매크로를 함수 같은 매크로(function-like macro) 또는 매크로 함수라고 부른다. 매크로 함수는 일반 함수와는 달리 단순 치환만을 해주므로, 일반 함수와 완전히 똑같은 방식으로 동작하지는 않는다. 일반 함수는 인수를 프로그램이 실행 중일 때 전달받지만, 매크로 함수는 인수를 컴파일 이전에 미리 치환하기 때문이다. 매크로 함수가 일반 함수처럼 작동하기 위해서는 아래의 사항에 주의하여 작성해야한다.
- 매크로 함수의 전체를 괄호(())로 감싸야 한다.
- 매크로 함수의 인수들도 각각 괄호로 감싸야 한다.
- 매크로 함수를 호출할 때에는 증감 연산자(++, --)나 복합 대입 연산자 등은 사용하지 않는 것이 좋다.
가변 인자를 가져올 수 있도록 포인터를 설정한다. 여기서 v
는 고정매개변수이다.
가변 인자 포인터에서 특정 자료형 크기만큼 값을 가져온 뒤, 자료형 크기만큼 순방향으로 이동한다.
가변 인자 리스트를 복사한다. 복사시점에 영향을 받기 때문에 복사할때의 src
리스트의 위치를 복사한다.
가변 인자 처리가 끝났을 때 포인터를 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