프로그래밍 언어/C언어

C언어 가변인자란?

원원 2020. 8. 5. 21:39

안녕하세요 오늘은 가변인자에 대해 알아보겠습니다

가변인자란 인자의 개수가 변하는 것 입니다.

예를들어 정수2개를 입력받아서 그 합을 구하는 함수와, 정수3개를 입력받아서 그 합을 구하는 함수를 만들려면 함수 2개를 만들어야합니다

 

정수2개를 합하는 함수

int sum2(int a, int b)
{
    return a+b;
}

 

정수3개를 합하는 함수

int sum3(int a, int b, int c)
{
	return a+b+c;
}

그러나 가변인자를 사용하면 함수를 1개만 만들어도 됩니다.

*가변인자 사용방법
1. 헤더파일포함시키기
2. 가변함수만들기

1. 헤더파일포함시키기
가변인자를 사용하려고하면 몇가지 매크로와 자료형을 사용하기위해서 헤더파일을 포함시켜야합니다
#include<stdarg.h>

2. 가변함수만들기

int sum(int count, ...) 
{
    va_list list;
    
    int sum = 0;
    int i;
    va_start(list,count);
    
    for(i=0; i< count ; i++)
        sum+= va_arg(list,int);
    va_end(list);
    return sum;
}
 

첫번째줄 : 인자로 int count와 줄임표(...)이 있습니다. 여러개의 인자선언 후에 줄임표가 나와야 합니다.
줄임표의 의미는 0개이상의 가변인자가 있다는 의미입니다.
세번째줄 :  va_list는 보이드형 포인터로써, 어떤 타입에도 사용할 수 있습니다.
일곱번째줄 : va_start(list,count); 는 list를 초기화하는 의미입니다. 초기화한다는 의미는 list포인터를 맨 처음으로 돌리는 의미입니다. count는 함수에 전달되는 마지막 고정인자를 의미합니다
열번째줄: 현재 list의 타입은 int인 것을 의미합니다
열한번째줄 : 가변인자의 사용을 끝낼 때 사용합니다

#include <stdio.h> 
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

int sum(int count, ...) 
{
    va_list list;
    
    int sum = 0;
    int i;
    va_start(list,count);
    
    for(i=0; i< count ; i++)
        sum+= va_arg(list,int);
    va_end(list);
    return sum;
    
}

int main(void) 
{ 
    printf("%d \n",sum(2, 1, 2 ));
    printf("%d \n",sum(3, 1, 2, 3 ));
    printf("%d \n",sum(4, 1, 2, 3, 4));
}
 

-> 여기서 중요한 게 sum(3,1,2,3)를 예로 들면, count가 2이고 va_arg(list,int) 할 때마다 1,2,3가 호출되는 것입니다.

*가변인자 매크로
1. void va_start(va_list list, last);
- va_list list : void형 포인터로써, 어떤 타입으로든 사용할수 있게 해줍니다
- last : 함수에 전달되는 마지막 고정인자를 의미합니다

2. type va_arg(va_list list, type);
- va_list list
- type : 인자 타입입니다.
- return : 인자

3. void va_end(va_list list);
가변인자 사용을 끝낼때 사용합니다 가변인자 포인터를 널로 초기화합니다
*다양한 인자타입을 사용하는 방법

#include <stdio.h> 
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

void infor(char * type, ...)
{
    va_list list;
    int i =0 ;
    va_start(list,type);
    for(i = 0 ; type[i] != '\0' ; i++)
    {
        switch(type[i])
        {
            case 'i':
                printf("int값 : %d \n", va_arg(list,int));
                break;
            case 's':
                 printf("*char값 : %s \n", va_arg(list,char*));
                break;
            default:
                break;
        }
    }
    va_end(list);
}

int main(void) 
{ 
    infor("si","HI",2020);   
    infor("ii",2020,805);
}
 

*vsnprintf함수
vsnprintf를 사용하면 전달받은 값을 버퍼에 저장하고 길이를 리턴합니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdarg.h>



void myPrintf(char *fmt, ...)
{
	int len;
	char buf[256];
	va_list args;
	va_start(args,fmt);
	len = vsnprintf(buf,256,fmt,args);
	printf("길이 : %d \n",len); 
	printf("%s",buf);
	va_end(args);
}

int main() {
	myPrintf((char *)"wowon %d",11);
}

길이 : 8
wowon 11
해당함수는 MCU에서 UART통신으로 송신할때 사용하면 좋습니다.