안 쓰던 블로그

C언어 가변인수함수(printf등) 내부구조 본문

언어/C, C++

C언어 가변인수함수(printf등) 내부구조

proqk 2016. 3. 30. 00:20
반응형

가변 인수란 인수의 개수와 타입이 정해져 있지 않은 인수를 뜻한다. 대표적으로 printf와 scanf 등이 있으며 여기서는 printf에 대해서 설명할 것이다.


1
2
3
4
printf(“Hello, World!”);
 
printf(“%d:%d”, a, b);
 
cs


printf 함수 호출 예시다. C언어를 쓰는 사람이라면 아주 친숙한 문장일 것이다.

이렇듯 문자열이든 정수든 개수가 한개든 두개든 잘 실행이 된다. 바로 가변 인수 덕분이다.




비주얼 스튜디오에서 printf를 입력하고 마우스를 갖다대보면 친절하게 printf의 원형을 설명해준다.

가변인수함수에서는 반드시 고정인수를 한개이상 가지고 있어야 하며, 가변인수가 올 자리에는 ...가 있다.


여기서는 Format가 문자열 상수를 의미하고, 고정인수다.

고정인수는 const char*타입의 문자열이여야만 한다.


cdecl은 함수를 호출할 때마다 호출원이 인수를 전달한 스택을 정리한다.

printf는 인수의 수가 정해져있지 않기 때문에 호출된 함수가 스택을 정리하는 __stdcall를 쓸 수가 없다.

이것은 모든 가변 인수에서 동일하게 적용되며, 만약 __stdcall로 작성했다면 컴파일할 때 __cdecl로 바꾸어버린다.


-

가변인자를 사용하는데 쓸 수 있는 매크로 함수들이 존재한다.

모두 <stdarg.h> 헤더파일을 호출하면 사용할 수 있다.


va_list

함수로 전달되는 인수들은 스택에 저장한 뒤 거기서 매개변수를 꺼내 사용하는데, 변수를 읽으려면 포인터 변수가 필요하며 그 포인터가 바로 va_list형인 것이다.


va_start

포인터 변수가 첫번째 가변인수를 가리키도록 초기화시킨다.


va_arg

va_start로 포인터 변수가 첫번째 가변인수를 가리키고 읽을 때 가변 인자를 읽는다.


va_end

가변인수를 다 읽은 다음에 정리하는 역할인데 없어도 별로 상관은 없다.




완성된 코드는 아니지만 대충 형식을 알아볼 수 있다.

1. Func함수가 첫번째 인수로 size를 전달받았다.

2. va_list로 Nstart라는 포인터 변수(char*형)을 지정했다.

3. va_start로 Nstart가 첫번째 인수 size를 가리킨다.

4. for문이 돌아가며 모든 인수를 다 읽을 때까지 계속 반복하며 읽는다.

5. 모든 인수를 다 읽었으면 va_end로 마무리한다.





반응형
Comments