debug_printf 함수는 가변 인자 처리기능을 구현한다.
함수의 매개변수로 받는 ...는 가변인자를 의미한다.
#ifndef LIB_STDIO_H_
#define LIB_STDIO_H_
uint32_t putstr(const char* s);
uint32_t debug_printf(const char* format, ...);
#endif
stdio.c 에 debug_printf를 선언해준다.
#include "stdint.h"
#include "HalUart.h"
#include "stdio.h"
#define PRINTF_BUF_LEN 1024
static char printf_buf[PRINTF_BUF_LEN]; // 1KB
uint32_t putstr(const char* s)
{
uint32_t c = 0;
while(*s)
{
Hal_uart_put_char(*s++);
c++;
}
return c;
}
uint32_t debug_printf(const char* format, ...)
{
va_list args;
va_start(args, format);
vsprintf(printf_buf, format, args);
va_end(args);
return putstr(printf_buf);
}
가변인자 처리를 위해 va_list , va_start, va_end가 추가되고
형식 지정자 처리는 vsprintf에서 수행된다.
stdarg.h에 가변인자 처리를 위한 컴파일러 빌트인 함수들을 재정의한다.
va_는 컴파일러 빌트인 함수이다.
#ifndef INCLUDE_STDARG_H_
#define INCLUDE_STDARG_H_
typedef __builtin_va_list va_list;
#define va_start(v, l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
#endif /* INCLUDE_STDARG_H_ */
- va_list
가변 인자 리스트를 관리하기 위한 타입. (typedef __builtin_va_list va_list;) - va_start(va_list, format)
- va_list를 초기화하여, format 인자 다음의 가변 인자를 순차적으로 읽을 준비를 함.
- 여기서 format은 debug_printf(const char* format, ...)의 첫 번째 인자임.
- va_arg(va_list, type)
- va_list에서 특정 타입(type)의 데이터를 하나씩 꺼내는 역할을 함.
- 예를 들어, va_arg(args, int) 하면 args 리스트에서 int 타입 하나를 꺼냄.
- va_end(va_list)
- 가변 인자 처리를 마친 후 정리하는 역할을 함.
2. vsprintf(printf_buf, format, args)의 의미
vsprintf 함수는 일반적인 sprintf와 비슷하지만, 가변 인자를 직접 전달받아 처리하는 기능이 있어.
즉, debug_printf에서 vsprintf를 호출하면:
- format 문자열과 args에 들어있는 가변 인자들을 참조해서 형식 지정자(%d, %s, %f 등)를 실제 값으로 치환하여 printf_buf에 문자열을 저장해.
- 이후 putstr(printf_buf)를 호출해서 UART로 문자열을 전송하게 됨.
오답 내용.
uint32_t utoa(char* buf, uint32_t val, utoa_t base)
{
const char asciia = 'a';
uint32_t c=0;
int32_t idx=0;
char tmp[11];
do{
uint32_t cur = val%base;
if(cur>=10)
{
cur= asciia - '0' - 10;
}
tmp[idx++]=cur+'0';
val/=base;
}while(val);
while(idx<=0)
{
buff[c++]=tmp[idx--];
}
return c;
}
3. 오답 및 정리
1) utoa_t 를 강제 형변환 안해줘도 되나?
-> utoa_t 는 enum으로 선언되었고 int 형으로 선언되어있기에 uint32_t를 강제형변환 시켜줘야 안전하게 처리됨.
2) for(uint32_t i=0;format[i];i++)
-> format의 마지막까지 진행. 마지막은 '\0'이 존재함으로 해당 조건 도달시 0이 되기에 끝까지 읽겠다는 의미.
'SW 개발 공부 > OS 개발 프로젝트' 카테고리의 다른 글
[나빌로스] RTOS 컨텍스트 스위칭 정리 (Round Robin + 선점형 기반) (0) | 2025.04.08 |
---|---|
[나빌로스] 10.컨텍스트 스위칭 (0) | 2025.04.02 |
[나빌로스] 8.태스크 (0) | 2025.04.02 |
[나빌로스] 7.타이머 (0) | 2025.04.02 |
[나빌로스] 5. UART (0) | 2025.03.29 |