1. 程式人生 > 其它 >linux C 可變引數型別va_list

linux C 可變引數型別va_list

目錄

可變函式引數,會用到va_list系列巨集,在C中用於定義可變引數列表,包含可變引數資訊。

常用的va_list系列巨集

包含:

  • va_start(ap, last)巨集:初始化可變引數列表;
  • va_arg(ap, type)巨集:返回下一個引數;
  • va_copy(dest, src)巨集:複製引數列表指標,將dest初始化為src;
  • va_end(ap)巨集:結束使用可變引數列表,會清空引數列表,置引數ap無效;

其宣告如下:

#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);

例如,我們常用的C庫函式printf,就用到了可變引數列表

#include <stdio.h>
int printf(const char *format, ...);

形參列表裡的 "..."代表0個或多個引數。

將可變引數由“...”轉換為va_list型別形式,

#include <stdarg.h>

int vprintf(const char *format, va_list ap);

va_list系列巨集使用模式

對於自定義可變引數列表的函式,可用va_list系列巨集,按如下模式對可變引數進行解析:

void func(type v, ...) 
{
    va_list(ap, v); // 定義一個指向個數可變的引數列表指標
    va_start(ap, v); // 使指標ap指向函式引數列表的第一個可選引數,v是第一個可選引數之前的固定引數
    
    while () {
        type tmp = va_arg(ap, type); // 返回引數列表中指標ap所指的引數,返回型別為type,並使指標ap指向下一個引數
    }

    va_end(ap); // 清空引數列表,並置引數列表指標ap無效
}

例1:定義一個可變引數的求和函式

int sum(int v, ...)
{
    int i = v;
    int s = 0;

    va_list ap;
    va_start(ap, v);

    while (i > 0) {
        s += va_arg(ap, int);
        i--;
    }

    //  {
    volatile int tmp = va_arg(ap, int); // tmp是未知值
    printf("tmp = %d\n", tmp);
    // } 用於測試

    va_end(ap);

    return s;
}

呼叫:

int main()
{
    int s = sum(3,2,3,4);
    printf("sum = %d\n", s);
    return 0;
}

執行結果:

tmp = -1392657952
sum = 9

例2:定義一個自定義列印字串函式

void my_print(const char *fmt, ...)
{
    char *s = fmt;
    va_list ap;

    va_start(ap, fmt);

    while (s != NULL) {
        printf("%s\n", s);
        s = va_arg(ap, char *);
    }

    va_end(ap);
}

呼叫:

int main()
{
    my_print("hello", "yes", "no");
    return 0;
}

執行結果:

hello
yes
no