閱讀436 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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

  上一篇:go android移動view
  下一篇:go 數據公鑰加密和認證中的私鑰公鑰