可變引數應用
利用可變引數列表:可變引數列表是通過巨集來實現的,這些巨集定義在stdarg.h中。
值得注意的是:可變引數列表傳參時,第一個傳的引數的個數。
步驟:
1.定義一個va_list型別的變數 arg
2.巨集va_start(arg,num)---這個巨集有兩個引數,第一個引數為va_list型別的變數,第二個引數為可變引數列表之前的引數。作用就是使得 va_list 的變數指向可變引數列表的首地址。這才是一般意義上的對 va_list的初始化。
3.巨集va_arg(arg,int) ---第一個引數為va_list型別的變數第二個為引數的型別。
4.巨集va_end(arg)---結束標誌
使用可變引數,實現函式,求函式引數的平均值
程式碼如下:
- #include<stdio.h>
- #include<stdlib.h>
- #include <stdarg.h>
- int average(int num, ...)//第一個引數傳的是引數的個數,後面三個點代表可變引數列表
- {
- int sum = 0;
- va_list arg; //定義一個va_list型別的變數
- va_start(arg, num); //巨集 va_start
- for (int i = 0; i < num; i++)
- {
- sum += va_arg(arg, int
- }
- va_end(arg); //巨集 va_end
- return sum / num;
- }
- int main()
- {
- int aver = 0;
- aver = average(5,2,4,6,8,10); //第一引數為個數,之後的數為被平均的數
- printf("%d\n", aver);
- system("pause");
- return 0;
- }
程式碼如下:
- #include <stdio.h>
- #include <stdarg.h>
- #include <windows.h>
- int Max(int n, ...)
- {
- int i = 0;
- int max = 0;
- va_list arg;
- va_start(arg, n);
- for (i = 0; i < n; i++)
- {
- int val = va_arg(arg, int);
- if (val > max)
- {
- max = val;
- }
- }
- va_end(arg);
- return max;
- }
- int main()
- {
- int ret = Max(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
- printf("%d\n", ret);
- system("pause");
- return 0;
- }
在C語言中常用printf函式輸出各種型別的數值,而且輸出的引數可多可少,這就涉及到了可變引數函式的定義。
在此模擬實現printf函式,可完成下面的功能,能完成下面函式的呼叫。 print("s ccc d.\n","hello",'b','i','t',100); 函式原型: print(char *format, ...)
程式碼如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include<stdarg.h>
void print(char *tmp, ...) //實現可變形參
{
va_list arg; //宣告va_list型別的變數arg,用於訪問引數列表的未確定部分
va_start(arg, tmp); //呼叫va_start來初始化。它的第一個引數是va_list的變數名,第2個引數是省略號前最後一個有名字的引數。初始化過程把arg變數設定為指向可變引數部分的第一個引數。
while (*tmp != '\0')
{
if (*tmp == 'c')
{
putchar(va_arg(arg, char )); //定義va_arg來訪問引數,這個巨集接受兩個引數:va_list變數和引數列表中下一個引數的型別。
}
else if (*tmp == 's')
{
puts(va_arg(arg, char *));
}
else if (*tmp == 'd')
{
int d = va_arg(arg, int);
printf("%d", d);
}
tmp++;
}
va_end(arg); //最後,當訪問完最後一個可變引數之後,我們需要呼叫va_end。
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
print("sccc d\n", "hello", 'b', 'i', 't',100);
getchar();
system("pause");
return 0;
}
但是,可變引數會有一些限制,例如:
1.可變引數必須從頭到尾逐個訪問。如果你在訪問幾個引數之後想要終止,這是可以的,但是,如果你要訪問中間的引數,那是不行的。
2.可變引數中至少有一個命名引數。如果連一個命名引數都沒有,就無法使用va_start。
3.這些巨集無法判斷每個引數的型別。
4.這些巨集無法直接判斷實際存在引數的數量。
5.如果在va_arg中指定了錯誤的型別,那麼後果是不可預測的。
希望這些對大家有所幫助。