c語言中可變參數的原理---printf()函數

 函數原型: int printf(const char *format[,argument]...)
       返 回 值: 成功則返回實際輸出的字符數,失敗返回-1.
 函數說明:
       在printf()函數中,format後面的參數個數不肯定,且類型也不肯定,這些參數都存放在棧內.調用printf()函數時,根據format裏的格式("%d %f...")依次將棧裏參數取出.而取出動做要用到va_arg、va_end、va_start這三個宏定義,再加上va_list.
     (1)va_list事實上是一char *類型,即:
            typedef char* va_list;
     (2)三個宏定義:
            #define _INTSIZEOF(n)    ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) 
            #define va_start(ap,v)     ( ap = (va_list)&v + _INTSIZEOF(v) ) 
            #define va_arg(ap,type)  ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) 
            #define va_end(ap)          ( ap = (va_list)0 ) 
   【attention】c語言中可變參數的原理---printf()函數 
            int printf(const char* format,...);   
      使用過C語言的人所再熟悉不過的printf函數原型,它的參數中就有固定參數format和可變參數(用」…」表示).而程序員又能夠用各類方式來調用printf,如: 
            printf("%d ",value);   
            printf("%s ",str);   
            printf("the number is %d,string is:%s ",value,str); 
       能夠看出,該函數的參數格式不固定,參數類型不固定.在C語言中使用宏來處理這些可變參數.這些宏看起來很複雜,其實原理挺簡單,即根據參數入棧的特色從最靠近第一個可變參數的固定參數開始,依次獲取每一個可變參數的地址.
 (1)宏va_start
      經過該宏定義能夠獲取到可變參數表的首地址,並將該地址賦給指針ap.
 (2)宏va_arg
      經過該宏定義能夠獲取當前ap所指向的可變參數,並將指針ap指向下一個可變參數.注意,該宏的第二個參數爲類型.
 (3)宏va_end
      經過該宏定義能夠結束可變參數的獲取.
程序員


      程序員經過這三個宏定義就能夠實現對可變參數的處理.例如:
app

[c-sharp]  view plain copy
  1.    #include <stdio.h>  
  2.   
  3. typedef char* va_list;   
  4.    #define _INTSIZEOF(n)    ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )   
  5.    #define va_start(ap,v)   ( ap = (va_list)&v + _INTSIZEOF(v) )   
  6.    #define va_arg(ap,type)  ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )   
  7.    #define va_end(ap)       ( ap = (va_list)0 )   
  8.   
  9. int cal_val(int c, ...)   
  10. {   
  11.     int sum = c;   
  12.     va_list ap;              //聲明指向char型的指針  
  13.     va_start(ap,c);          //獲取可變參數列表的首地址,並賦給指針ap  
  14.   
  15.     c = va_arg(ap,int);      //從可變參數列表中獲取到第一個參數(返回值即爲參數)  
  16.     while(0 != c)   
  17.     {   
  18.         sum += c;   
  19.         c = va_arg(ap,int);  //循環的從可變參數列表中獲取到參數(返回值即爲參數)  
  20.     }  
  21.     va_end(ap);              //結束從可變參數列表中獲取參數  
  22.     return sum;   
  23. }    
  24.    
  25. int main(int argc, char* argv[])   
  26. {   
  27.     int value1;  
  28.       
  29.     value1 = cal_val(1,2,3,4,5,6,7,8,9,0);   
  30.     printf("value1=%d/n",value1);  
  31.     value2 = cal_val(6,7,8,9,0);   
  32.     printf("value2=%d/n",value2);  
  33.       
  34.     return 0;   
  35. }   

 

C99就支持可變參數宏 ,兩種寫法: 函數

#define   dbgprint(format,args...)   \  
                  fprintf(stderr,   format,   ##args)  
#define   dgbmsg(fmt,...)   \  
                            printf(fmt,__VA_ARGS__)   spa

相關文章
相關標籤/搜索