C語言中的不定參數


三個宏的使用va_arg()、va_start()和va_end()
上述的宏原型如下所示:

type va_arg(va_list argptr, type);  
void va_end(va_list argptr);  
void va_start(va_list argptr, last_parm);  

 

  
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1)) //類型n的大小,這是考慮了字節對齊
#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //ap指向第一個不定參數地址
#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一個參數地址  返回當前ap指向的值,並且增加ap
#define va_end(ap) ( ap = (va_list)0 ) // 將指針置為無效

總結:讀取可變參數的過程其實就是堆棧中,使用指針,遍歷堆棧段中的參數列表,從低地址到高地址一個一個地把參數內容讀出來的過程.

3,不定參數函數有個限制,就是不定參數的列表必須在整個函數的參數列表的最后。
我們不可以定義如下的函數:
  void func(int a, ……, int c)
  所有類型固定的參數都必須出現在參數列表的開始。
  在設計具有不定參數列表的函數的時候,我們有兩種方法來確定到底多少參數會被傳遞進來。
  方法1是在類型固定的參數中指明后面有多少個參數以及他們的類型。printf就是采用的這種方法,它的format參數指明后面每個參數的類型。
  方法2是指定一個結束參數。這種情況一般是不定參數擁有同樣的類型,我們可以指定一個特定的值來表示參數列表結束。

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

int sumi(int c, ...)
{
    va_list argptr;
    va_start(argptr, c); //初始化變元指針
    int sum = c;
    c = va_arg(argptr, int); //作為下一個參數類型的參數類型,返回不定參數
    //c保存第一個不定參數
    printf("%d\n", c);
    while(0 != c) //末尾特定字符指示結束
    {
        sum = sum + c;
        c = va_arg(argptr, int);
    }
    va_end(argptr);
    return sum;
}

double sum_series(int num, ...)
{
    double sum = 0.0, t;
    va_list argptr;
    va_start(argptr, num);//初始化變元指針
    while (num--)
    {
        t = va_arg(argptr, double);
        sum = sum + t;
    }
    va_end(argptr);
    return sum;
}

int main()
{
    int i = sumi(1,2,3,4,5,6,7,8,9,0);
    printf("%d\n", i);
    double d = sum_series(4, 1/3.0, 1/4.0, 1/5.0, 1/6.0);
    printf("%f\n", d);

    return 0;
}

mutian@mutian:~/soft$ ./a.out
2
45
0.950000


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM