본문 바로가기

Program Languege/혼자 연구하는 C/C++

가변 인수

가변 인수

 

 가변 인수란 말 뜻 그대로 인수의 개수가 미리 정해져 있지 않다는 뜻이며 그런 인수를 사용하는 함수를 가변 인수 함수라고 한다. 가장 좋은 예로 printf함수가 있다.

 

int printf(const char *format, ...);

 

 이 함수의 첫 번째 인수는 format이라는 이름의 문자열 상수인데 흔히 서식 문자열이라고 부른다. 두 번째 이후의 인수에는 타입과 인수 이름이 명시되어 있지 않으며 대신 생략 기호가

적혀있다. 생략 기호는 컴파일러에게 이후의 인수에 대해서는 개수와 타입을 점검하지 않도록 하는데 이 기호에 의해 가변 인수가 가능해진다.

 

가변 인수 함수의 개략적인 구조는 다음과 같다.( #include<stdarg.h>를 해주어야한다)

 

void VarFunc(int Fix, ...)

{

va_list ap;

va_start(ap, Fix);

while(모든 인수를 다 읽을 때까지)

{

va_arg(ap, 인수타입);

}

va_end(ap);

}

 

 마지막 인수 자리에만 ...만 있으면 가변 인수 함수가 된다. 가변 인수 함수 내부에서는 인수를 읽기 위해 매크로 함수가 필요하다.

 

va_list ap

 

 함수로 전달되는 인수들은 스택(Stack)이라는 기억 장소에 저장되며 함수는 스택에서 인수를 꺼내 쓴다. 스택에 있는 인수를 읽을 때 포인터 연산을 해야 하는데 현재 읽고 있는 번지를 기억하기 위해 va_list형의 포인터 변수 하나가 필요하다. ap는 어디까지나 지역변수일 뿐이므로 이름은 마음대로 정할 수 있되 관습적으로 가변 인수를 다루는 매크로에서는 ap라는 이름을 사용한다.

 

va_start(ap, 마지막 고정인수)

 

 이 명령은 가변 인수를 읽기 위한 준비를 하는데 ap 포인터 변수가 첫번째 가변 인수를 가리키도록 초기화한다. 첫 번째 가변 인수의 번지를 조사하기 위해서 마지막 고정 인수를 전달한다. va_start 내부에서는 ap가 마지막 고정 인수 다음 번지를 가리키도록 해주므로 이후부터 ap 번지를 읽으면 순서대로 가변 인수를 읽을 수 있다.

 

va_arg(ap, 인수타입)

 

 가변 인수를 실제로 읽는 명령이다. va_start가 ap를 첫 번째 가변 인수 번지로 맞추어 주므로 ap 위치에 있는 값을 읽기만 하면 된다. 단, ap 번지에 있는 값이 어떤 타입인지를 지정해야 이 매크로가 값을 제대로 읽을 수 있으므로 두 번째 인수로 읽고자 하는 값의 타입을 지정 한다.

 

va_end(ap)

 

 이 명령은 가변 인수를 다 읽은 후 뒷정리를 하는데 별다른 동작은 하지 않으며 실제로 없어도 전혀 지장이 없다. 이 명령이 필요한 이유는 호환성 때문인데 플랫폼에 따라서는 가변 인수를 읽은 후에 뒷처리를 해야하는 경우도 있기 때문이다. 적어도 인텔 계열의 CPU에서는 va_end가 아무 일도 하지 않는다. 그러나 다른 플랫폼에서는 va_end가 중요한 역할을 할 수도 있으므로 호환성을 위해서는 관례적으로 넣어 주는 것이 좋다.

 

 

 가변 인수 함수 조건

 

 1.반드시 하나 이상의 고정 인수를 가져야한다는 점이다. 첫번째 인수부터 가변 인수일 수는 없는데 왜냐하면 가변 인수를 읽기 위한 포인터 ap를 초기화하기 위해서

   마지막 고전 인수의 번지를 알아야하기 때문이다. va_start 매크로는 마지막 고정 인수의 번지에 길이를 더해 가변 인수가 시작되는 번지를 계산하는데 고정 인수가 없으면

   이 매크로가 동작하지 않는다. 하지만 컴파일러마다 함수를 호출할 때 스택을 조작하는 방법이 다르고 어셈블리를 직접 사용해야하기 때문에 일반적으로 불가능하다고 보는 편이 옳다.

 

 2.함수 내부에서 자신에게 전달된 가변 인수의 개수를 알 수 있도록 해야한다. 전달될 수 있는 인수의 개수에는 제한이 없으며 컴파일러는 함수가 호출될 때

   인수의 개수를 점검하지도 않는다. 그래서 호출측에서 가변 인수가 몇개나 전달되었는지를 알려 주지 않으면 함수 내부에서 인수의 개수를 알 수 있는 방법이 전혀 없다.

   함수 스스로 인수의 개수를 파악할 수 있도록 호출측이 정보를 제공해야 한다.

 

 3.개수와 마찬가지로 함수 내부에서 각각의 가변 인수 타입을 알 수 있어야한다. 모든 인수를 정수형으로 고정하든가 아니면 첫 번째, 두 번째는 실수, 세 번째 이후는

   모두 정수라는 식으로 미리 약속되어 있어야 한다.

 

 

출처 : http://www.soen.kr/

 

 

'Program Languege > 혼자 연구하는 C/C++' 카테고리의 다른 글

4.제어문  (0) 2014.02.10
3.변수  (0) 2014.02.07
2. 첫번째 예제  (0) 2014.02.04
01. 프로그래밍 입문  (0) 2014.02.04