程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C Primer Plus(第五版)學習筆記-可變宏:...和__VA_ARGS__,primer__va_args_

C Primer Plus(第五版)學習筆記-可變宏:...和__VA_ARGS__,primer__va_args_

編輯:關於C語言

C Primer Plus(第五版)學習筆記-可變宏:...和__VA_ARGS__,primer__va_args_


一 、__VA_ARGS__

P454 所講printf()這些輸出函數的參數是可變的,在調試程序時,可能希望定義參數為可變的輸出函數,

那麼可變參數宏會是一個選擇,例如:

#define DEBUG(X, ...) printf("Message", #X,":" __VA_ARGS__)

其中,...表示參數可變,__VA_ARGS__在預處理中為實際的參數集所替換部分。

//variadic.c----可變宏

 

#define DBG(format, ...) printf("Message"#format":File:%s, Line:%d, Function:%s" __VA_ARGS__,__FILE__, __LINE__ , __FUNCTION__)

int main(void)
{
   double x = 48;
   double y = 0;
   y = sqrt(x);


   DBG(1,"x=%g\r\n",x);
   DBG(2,"x=%.2f,y=%.4f\r\n",x,y);
   return 0;
}

 

二、若部分不支持__VA_ARGS__,可以采用下面方法

 

#define DEBUG_BUFFER_MAX_LENGTH 1024
void printDebugMsg( const char* format, ...)
{
    char buffer[DEBUG_BUFFER_MAX_LENGTH + 1]={0};
    va_list arg;
    va_start (arg, format);
    vsnprintf(buffer, DEBUG_BUFFER_MAX_LENGTH, format, arg);
    va_end (arg);
    printf( "%s", buffer );
}

int main(void)
{
   double x = 48;
   double y = 0;
   y = sqrt(x);


   printDebugMsg("x=%g\r\n",x);
   printDebugMsg("x=%.2f,y=%.4f\r\n",x,y);
   return 0;
}

 

    三、可變參數(P487)
int SqSum(int n1, ...)
{
    va_list arg_ptr;
    int nSqsum = 0;
    int n = n1;
    va_start(arg_ptr,n1);

    while(n > 1)
    {
        nSqsum +=(n*n);
        n = va_arg(arg_ptr,int);
    }

    va_end(arg_ptr);

    return nSqsum;
}

int main(void)
{
    int nSqSum = SqSum(2,3,4,5,-1);
    printf("sqsum = %d\r\n",nSqSum);
    return 0;
}
int SqSum(int n1, ...)參數可以分為兩部分:個數確定的固定參數和個數可變的可選參數。函數至少需要一個固定參數,固定參數的聲明和普通函數一樣;可選參數由於個數不確定,聲明時用"…"表示。固定參數和可選參數公同構成一個函數的參數列表。

分析上面例程,來看看各個va_xx的作用:
va_list arg_ptr:定義一個指向個數可變的參數列表指針;
va_start(arg_ptr, argN):使參數列表指針arg_ptr指向函數參數列表中的第一個可選參數,說明:argN是位於第一個可選參數之前的固定參數,(或者說,最後一個固定參數;…之前的一個參數),函數參數列表中參數在內存中的順序與函數聲明時的順序是一致的。如果有一va函數的聲明是void va_test(char a, char b, char c, …),則它的固定參數依次是a,b,c,最後一個固定參數argN為c,因此就是va_start(arg_ptr, c).
 
va_arg(arg_ptr, type):返回參數列表中指針arg_ptr所指的參數,返回類型為type,並使指針arg_ptr指向參數列表中下一個參數。
va_copy(dest, src):dest,src的類型都是va_list,va_copy()用於復制參數列表指針,將dest初始化為src。
va_end(arg_ptr):清空參數列表,並置參數指針arg_ptr無效。
 
說明:指針arg_ptr被置無效後,可以通過調用va_start()、va_copy()恢復arg_ptr。每次調用va_start() / va_copy()後,必須得有相應的va_end()與之匹配。參數指針可以在參數列表中隨意地來回移動,但必須在va_start() … va_end()之內。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved