C언어에서 그게 되는거였어?
최근에 알게 된 사실인데 C언어도 가변 인자 함수를 사용할 수 있습니다. 가변 인자 함수가 무엇이냐 하면 함수의 인자(인수) 개수가 고정되어있지 않은 것을 말합니다. C언어라고 하면 오래된 만큼 조금 고리타분하다는 인상을 받고 있었습니다. 그래서 그렇게 유연한 기능이 있다는 것을 생각지도 않고 있었지요.
그런데 가만히 생각해보면 평소에 가변 인자 함수를 아주 흔하게 사용하고 있었습니다. 바로 printf()
함수이지요. 첫 번째 인자에 출력하고자 하는 문자열 형식(template
)이 들어가고 그 이후부터는 앞서 정한 형식에 들어가는 변수들을 나열하지요. 문자열 형식을 어떻게 작성했느냐에 따라 뒤따라오는 인자가 0개가 될 수도 있고 2개, 3개, 10개도 될 수 있습니다.
가변 인자 함수, 어떻게 만들지?
gcc 매뉴얼에서 printf()
함수를 찾아보았습니다. 첫 번째 인자는 문자열 형식을 정하는 const char *template
입니다. 그리고 뒤따라 나올 가변 인자 부분은 점 3개(...
)로 표현하고 있습니다.
int printf (const char *template, …)
가변 인자 함수를 구현할 때 반드시 고정 인자 하나를 만들어야 합니다. 그리고 그 뒤에 이어서 , ...
를 추가하면 이것이 가변 인자 함수가 됩니다.
인자는 어떻게 불러오면 될까?
가변 인자를 처리하기 위해서는 우선 stdarg.h
라는 헤더 파일을 포함해야 합니다. 그리고 가변 인자에 접근할 수 있는 주소를 담을 va_list
형의 변수를 준비하고, va_start()
, va_arg()
, va_end()
를 이용해 가변 인자를 처리합니다. 이 va_
로 시작하는 '인자 접근 매크로(argument access macro)'의 간단한 설명은 아래와 같습니다.
va_list
- 가변 인자를 가리키는 포인터 변수 형(type) 입니다.
va_start
- 인수가 시작되는 위치를 va_list형의 변수가 가리키도록 합니다.
va_arg
- 현재 va_list가 가리키고 있는 인수를 반환합니다.
- 인수 형을 지정해 주어야 합니다.
- 이때 Self promoting 되는 형이어야 합니다. (Self promoting이 정확히 뭘 의미하는지는 아직 잘 모르겠습니다)
- 위의 조건 때문에 char, float, short int는 사용할 수 없습니다.
- 값을 가지고 오면 자동으로 va_list는 다음 인자를 가리킵니다.
va_end
- 가변 인수 접근을 마칠 때 호출합니다.
인자 접근 매크로에 관한 조금 더 자세한 내용은 gcc 매뉴얼을 참고하는 게 좋겠습니다. 아래는 공식 문서에 나와 있는 예시 코드입니다. 인자 접근 매크로를 어떻게 사용하는지 이해하는 데 도움이 될 것입니다.
int
add_em_up (int count,...)
{
va_list ap;
int i, sum;
va_start (ap, count); /* Initialize the argument list. */
sum = 0;
for (i = 0; i < count; i++)
sum += va_arg (ap, int); /* Get the next argument value. */
va_end (ap); /* Clean up. */
return sum;
}
int
main (void)
{
/* This call prints 16. */
printf ("%d\n", add_em_up (3, 5, 5, 6));
/* This call prints 55. */
printf ("%d\n", add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
return 0;
}
덧
이 가변 인자 함수 때문에 한 가지 사실을 깨달았습니다. 'C언어를 너무 모르고 있구나'라는 것을요. 돌이켜보면 C언어 입문서로 공부하고 난 뒤 중, 상급으로 넘어가는 제대로 된 공부를 하지 않았습니다. 물론 책상에 앉아 책 펴서 각 잡고 있는 것만이 공부가 아니라고 생각합니다. 인터넷에서 충분히 좋은 자료가 많습니다. 그런데 뭘 알아야 검색을 하지요. 내가 모르는 게 무엇인지 모르는 상태라면 검색을 통해 부족함을 채우는 일에 한계가 있을 것입니다.
이번 기회를 통해 C언어를 다시 복습해보자는 마음가짐이 생겼습니다. 조금 더 고급 정보가 담긴 자료를 찾는 것부터 시작해야겠네요.
'연구 노트 > C, C++' 카테고리의 다른 글
C++를 사용할 수 있는 GUI 라이브러리 모음 (0) | 2022.08.24 |
---|---|
[다시 C언어] 함수 반환형, 안적어도 될까? (0) | 2021.02.18 |
[다시 C언어] 시작하며. (0) | 2021.02.18 |
구조체 내부 변수 뒤 이것 ':'의 정체, '비트 필드' (0) | 2021.01.26 |
헤더 파일 중복 방지 왜 필요할까? (0) | 2019.08.31 |