printf() 함수 구현 중에 마주친 가변 인수의 개념.
대충 "바뀔 수 있는 인수"라는 뜻인 것 같은데 언제 어디에서 사용되는 개념인지 알아보자.
가변 인수 (Variable Argument)
가변 인수는 미리 정해져 있지 않은 인수를 의미한다. 즉, 인수의 개수와 자료형이 따로 정해져 있지 않은 인수라는 뜻이다. 가변 인수 함수란 이러한 가변 인수를 다루는 함수이다. 이렇게 풀어쓰니 잘 와닿지 않는 것 같지만 사실 나는 이미 가변 인수 함수를 사용하고 있었다. 바로 printf() 함수가 가변 인수를 가지는 함수의 대표적인 예시이다.
먼저 아래는 오리지널 printf() 함수의 프로토타입이다.
int printf(const char *format, ...);
내가 구현해야 하는 ft_printf() 함수 또한 이 프로토타입과 크게 다르지 않다. 첫 번째 인수인 format 부분과 관련된 부분은 이전 게시물에서 살펴봤으므로 ". . ." 으로 표현된 뒷부분을 살펴보자.
이 부분이 바로 가변 인수와 관련된 부분인데, 인수 위치에 ". . ."을 넣어놓으면 해당 인수의 개수와 자료형을 확인하지 않고 들어오는 그대로 함수에 넘겨준다. 따라서 개수와 자료형이 따로 정해져 있지 않은 가변 인수를 선언하기에 적합하다.
가변 인수 사용법
가변 인수를 사용하려면 가변 인수를 컨트롤하는 C 표준 라이브러리 <stdarg.h> 를 추가해주어야 한다. IBM 문서는 <stdarg.h>를 이렇게 설명한다.
<stdarg.h> 포함 파일은 가변 길이 인수 리스트를 포함하는 함수에서 인수에 액세스할 수 있는 매크로를 정의합니다(va_arg(), va_copy(), va_start(), va_end()). <stdarg.h> 포함 파일은 유형 va_list도 정의합니다.
그러니까 위의 매크로 함수들을 사용하기 위해서 <stdarg.h>를 include한다는 것이다.
가변 인수들은 연속된 스택 메모리 공간에 할당된다. 스택에서 인수를 꺼낼 때는 포인터 연산을 사용하는데 이를 위해서 함수 안에 va_list형 변수를 선언해주어야 한다.
va_list()
va_list ap;
char* 형으로 가변 인수의 목록을 나타내는 포인터이다.
int 형 변수를 대개 n으로 선언해주는 것처럼 va_list()형은 argument pointer의 줄임으로 ap를 자주 쓰는 듯 하다.
va_start()
va_start(ap, 가변인수 시작 전 매개변수);
va_list()를 초기화하고 가변 인수 목록에서 첫 번째 인수를 가리키도록 포인터를 설정한다.
va_arg()
va_arg(ap, 가변인수의 자료형-ex. int, long 등);
현재 포인터가 가리키는 주소에서 특정 자료형의 크기만큼 값을 꺼내 반환하고, 다음 인수로 이동한다.
va_end()
va_end(ap);
가변 인수 목록을 정리하고 정리된 목록을 더 이상 사용하지 않도록 포인터를 NULL로 초기화 해준다.
(호환성 문제 때문에 넣어주는 것이고, 넣어주지 않아도 잘 작동한다고 함)
va_copy()
va_copy(va_list dest, va_list src);
src에 저장된 가변 인수 목록을 dest로 복사한다.
이처럼 가변 인수 함수는 한 번 호출될 때 다양한 인수를 처리할 수 있어 함수를 보다 유연하고 효과적으로 사용하는데 도움이 된다.
'42' 카테고리의 다른 글
[C] 정적변수란? - 지역변수, 전역변수 비교 (0) | 2024.02.08 |
---|---|
[C] printf() 함수란? (1) | 2023.12.06 |