Variable Length Arguments

Sunday, March 22, 2020

Variable Length Arguments

當輸入的引數長度不確定時,我們可以使用 Variable Length Arguments 來實作。
其來自於 <stdarg.h> 標準函式庫中

意義

va_list 為 variable argument lists
無論輸入的參數個數為何,皆可處理

實作原理

typedef char *va_list;
#define va_start(ap, param) (ap = (((va_list)&param) + sizeof(param)))
#define va_end(ap) (void)((ap) = 0)
#define va_arg(ap, type) (*(type *)((ap += sizeof(type)) - sizeof(type)))

用法

  • 宣告 資料型態為 va_list 的 ap (為 pointer)
va_list ap;

Macro 之 prototype

void va_start(va_list ap, last_arg);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
  • va_start:將 ap (pointer)設定成第一個參數的位址
  • va_arg: 將 ap 設定成下一個參數之位址
  • va_end: 表示走訪結束,ap 設定成 NULL
  • va_copy: 複製一份 va_list到 dest

例子

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

int sum(int, ...);
void print_name(const char *, ...);

int main() {
	int count = 3;
    printf("Sum of 1, 2, 3 = %d\n", sum(count, 1, 2, 3));
    count = 4;
    printf("Sum of 14, 2, 25, 30 = %d\n\n", sum(count, 14, 2, 25, 30));
    print_name("Sophie", "Meg", "Kenny", "Smith", "John");
    return 0;
}

int sum(int multi_nums, ...) {
    int total = 0;
    va_list ap;

    va_start(ap, multi_nums);
    for(int i = 0; i < multi_nums; i++) {
        total += va_arg(ap, int);
    }
    va_end(ap);
    return total;
}

void print_name(const char *firstStr, ...){
    va_list ap;
    va_start(ap, firstStr);
    int num = 0;
    const char* str = firstStr;
    while(str != NULL){
        printf("%d. %s\n", num+1, str);
        str = va_arg(ap, const char *);
        num++;
    }
    va_end(ap);

    printf("Total: %d people\n", num);   
}

編譯

gcc test.c -o0 -o test

執行

./test
Sum of 1, 2, 3 = 6
Sum of 14, 2, 25, 30 = 71

1. Sophie
2. Meg
3. Kenny
4. Smith
5. John
Total: 5 people

Reference

ProgrammingC程式

函式呼叫(I) - 參數傳遞

靜態分析工具介紹