C언어에서 stdarg.h 헤더를 사용하면 함수 선언 시 가변 인자(Variable arguments)를 가질 수 있다.


stdarg.h 헤더파일은 자료형으로 va_list를 가지며, 함수로 va_start, va_arg, va_end 등의 함수를 포함하고 있다.


아래의 예를 살펴보면 이해 할 수 있을 것이다.

#include<stdio.h>

#include<stdarg.h>


void vaPrintf(const char* sentence, ...){

int i;

va_list values;

va_start(values, sentence);

unsigned long long int iInt64;

double* iDouble_p;


for(i=0;;i++){

if(sentence[i] == 0) break;

else if(sentence[i] == '%'){

i++;

switch(sentence[i]){

case 'd' : printf("%d", va_arg(values, int));

break;

case 'c' : printf("%c", va_arg(values, unsigned int));

break;

case 'f' : printf("%f", (float)va_arg(values, double));

break;

case 's' : printf("%s", va_arg(values, char*));

break;

case 'x' : printf("%x", va_arg(values, unsigned int));

break;

case 'l' : if(sentence[i+1] == 'd'){

printf('%ld", va_arg(values, unsigned long long int));

}

else if(sentence[i+1] == 'f'){

printf("lf", va_arg(values, double));

}

else{

printf("ERROR: invalid format\n");

}

break;

defaut : printf("ERROR: invalid format\n");

break;

}

}

else{

printf("%c", sentence[i]);

}

}

}


void main(){

vaPrintf("vaPrintf test\n");

vaPrintf("int 1 = %d\n", (int)1);

vaPrintf("float 1.5 = %f\n", (float)1.5);

vaPrintf("double 1.5 = %lf\n", (double)1.5);

}

주의 해야할 점은 va로 float 을 넘기게 되면 넘어갈 때 double 형태로 넘어가게 된다고한다.(short, char 등도 int로 넘어간다.)

따라서 va_arg(va_list _list, type _t) 에서 type은 float 이 될 수 없다.

다만, function_call 시 float 을 인자로 넘긴다면, 이와같이 va_arg(_list, double) double 로 지정하더라도 할당 받는 변수의 형태에 맞춰 자동으로 float 으로 변환이 된다.(할당 받는 변수가 float 이면 float으로 자동으로 캐스팅/ double 이면 double로)

이와 같은 이유로, printf 함수에서도 double 자료형을 출력할 떄, %f / %lf 아무거나 써도 똑같이 double 형 캐스팅된 값을 출력하게 된다.


추가적으로 ARMCC 의 경우, 가변인자로 double/unsigned long long int 등 32bit 을 넘어가는 데이터가 제대로 넘어가지 않는 오류를 발견했다.

넘기기 전에 32비트씩 나누어 넘기고, 받아서 다시 data type을 바꿔주는 것이 좋을 듯 하다.





'Programming > C Language' 카테고리의 다른 글

C progress printing  (0) 2018.08.07
static  (0) 2018.07.13
extern  (0) 2017.06.21
static  (0) 2017.06.20
Floating Point Bit 출력 방법  (0) 2017.06.08

+ Recent posts