引入:最近在移植MPU6050的DMP库的时候遇到了许多问题,其驱动代码中有关打印日志的部分让我印象深刻,他的传参格式和printf很像,包括在做其他驱动移植参考别人的移植代码时,别人的串口输出函数也是用的printf关键字。这种传参方式在参数格式多变,数量多变的情况下着实有用。
这里我们先来了解一下传统printf函数的代码。。
int printf(const char *format, ...)
{
va_list L; //生成栈
int count=0; //用于记录参数个数
va_start(L,format);//指向栈中的第一个数据 (获取首指针)
count=vprintf(format,L);//轮询打印
va_end(L); //结束栈(清除)
return count;
}
从这段代码中可以知道:
不定参函数的定义格式 : 类型 函数名(参数,...){代码段;}
代码段是一堆用于处理参数的宏定义和一个返回值(这里用于返回参数个数)组成。
对于不定参函数最重要的宏命令有这三个:va_list , va_start , va_end 。
va_list | 定义一个用于存放不定参数的列表。 |
|
va_start | 指向首指针 |
|
va_end | 结束列表,释放内存 |
|
除去这三个,还有一些就是用于处理列表的函数了。比如,va_arg,vsprintf等。举个例子,试试下面这个函数。
int sum(int number,...)
{
int s=0;
va_list L;
va_start(L,number);
while( number--)
s=s+va_arg(L,int);
va_end(L);
return s;
}
不难看出这是一个任意个数整数求和的函数。我们发现这里的形参number是一个整型,指的是后面参数的个数。结合printf那个例子中的format,我们可以得出:不定参函数必须传入至少一个形参,用于修饰后面的不定参数。
那么在STM32中,则有
int USART_Printf(const char *format,...)
{
__va_list L;
char str[64]; //用于存放输出结果
__va_start(L,format);
vsprintf(str,format,L); //格式转换
Usart_SendString(USART1,str);//默认使用串口1
__va_end(L);
}
int OLED_Printf(const char *format,...)
{
__va_list L;
char str[64]; //用于存放输出结果
__va_start(L,format);
vsprintf(str,format,L); //格式转换
OLED_ShowString(0,0,str,20);//默认打印位置(x=0,y=0,str,字号20)
__va_end(L);
}
vsprintf函数可以参考sprintf,更多关于va_list数据格式的操作函数可以自己去标准库里找。
引入:最近在移植MPU6050的DMP库的时候遇到了许多问题,其驱动代码中有关打印日志的部分让我印象深刻,他的传参格式和printf很像,包括在做其他驱动移植参考别人的移植代码时,别人的串口输出函数也是用的printf关键字。这种传参方式在参数格式多变,数量多变的情况下着实有用。
这里我们先来了解一下传统printf函数的代码。。
int printf(const char *format, ...)
{
va_list L; //生成栈
int count=0; //用于记录参数个数
va_start(L,format);//指向栈中的第一个数据 (获取首指针)
count=vprintf(format,L);//轮询打印
va_end(L); //结束栈(清除)
return count;
}
从这段代码中可以知道:
不定参函数的定义格式 : 类型 函数名(参数,...){代码段;}
代码段是一堆用于处理参数的宏定义和一个返回值(这里用于返回参数个数)组成。
对于不定参函数最重要的宏命令有这三个:va_list , va_start , va_end 。
va_list | 定义一个用于存放不定参数的列表。 |
|
va_start | 指向首指针 |
|
va_end | 结束列表,释放内存 |
|
除去这三个,还有一些就是用于处理列表的函数了。比如,va_arg,vsprintf等。举个例子,试试下面这个函数。
int sum(int number,...)
{
int s=0;
va_list L;
va_start(L,number);
while( number--)
s=s+va_arg(L,int);
va_end(L);
return s;
}
不难看出这是一个任意个数整数求和的函数。我们发现这里的形参number是一个整型,指的是后面参数的个数。结合printf那个例子中的format,我们可以得出:不定参函数必须传入至少一个形参,用于修饰后面的不定参数。
那么在STM32中,则有
int USART_Printf(const char *format,...)
{
__va_list L;
char str[64]; //用于存放输出结果
__va_start(L,format);
vsprintf(str,format,L); //格式转换
Usart_SendString(USART1,str);//默认使用串口1
__va_end(L);
}
int OLED_Printf(const char *format,...)
{
__va_list L;
char str[64]; //用于存放输出结果
__va_start(L,format);
vsprintf(str,format,L); //格式转换
OLED_ShowString(0,0,str,20);//默认打印位置(x=0,y=0,str,字号20)
__va_end(L);
}
vsprintf函数可以参考sprintf,更多关于va_list数据格式的操作函数可以自己去标准库里找。
举报