C語言中的可變參數函數的淺析(以Arm 程序中的printf()函數實現為例) .
我們在C語言編程中會遇到一些參數個數可變的函數,一般人對它的實現不理解。例如Printf():
Printf()函數是C語言中非常常用的一個典型的變參數函數,它
的原型為: int printf( const char* format, ...);
它除了一個參數format固定外,後麵的參數的個數和類型是不確定的,如下列三種調用方法:
1. printf(“%d\n”, i);
2. printf(“%s\n”, “Hello World”);
3. printf(“The result is %d, name is %s”, i, “Lily”);
使用可變參數時,需要用到的庫函數:va_list 、va_start、va_arg、va_end,要包含頭文件<stdarg.h>
使用可變參數的步驟:
1)首先在函數裏定義一個va_list型的變量,如arg
2)然後用va_start宏初始化變量arg,這個宏的第二個參數是第一個可變參數的前一個參數,是一個固定的參數.
3)然後用va_arg返回可變的參數.依次取可變參數,va_arg的第二個參數是你要返回的參數的類型
4)最後用va_end宏結束可變參數的獲取.
現在你就可以在函數裏使用第二個參數了.如果函數有多個可變參數的,依次調用va_arg獲取各個參數.
應用:在ARM調用串口打印時,是沒有Printf()的,這時就需要自己寫一個打印函數(前提是已經實現串口的字符、字符串及整數打印)
void Uart_Printf(const char *format, ...)
{
va_list unnamed_p;
char *p, *sval;
unsigned int value_i;
/* unnamed_p point to first unnamed argument */
va_start( unnamed_p, format);
for ( p=(char *)format; *p!='\0'; p++ )
{
if ( *p != '%' )//循環檢測format的每位字符,沒有遇到“%”,//則輸出該字符
{
Uart_Put_Char( *p );
continue;
}
//如果遇到“%”,則是格式控製符,向下運行,指針p加1,確定是//“%d”、“%s”等,然後相應處理
switch ( *++p )
{
case 'd'://輸出十進製整數
value_i = va_arg( unnamed_p, unsigned int );
Out_Put_Int( value_i, 10 );
break;
#if 0
case 'c'://輸出字符
{
sval = va_arg(unnamed_p, char*);
Uart_Put_Char(*sval);//串口輸出字符函數
break;
}
#endif
case 's'://輸出字符串
for (sval = va_arg(unnamed_p, char*); *sval; sval++)
Uart_Put_Char( *sval ); //此為串口輸出字符函數
break;
case 'x': //X表示16進製
value_i = va_arg( unnamed_p, unsigned int );
Out_Put_Int( value_i, 16 );//此為串口輸出無符號整數函數,//第一個參數為要輸出的整數,第二個參數為進製,表示以多少進製//的格式輸出
break;
default: //輸出字符
Uart_Put_Char( *p );
break;
}
}
va_end( unnamed_p ); //結束可變參數的獲取
}
最後更新:2017-04-03 12:53:47