c - variadic function - 引數【個數】可變函式
參考
https://en.cppreference.com/w/c/variadic
https://en.cppreference.com/w/c/language/variadic
引數可變函式
The declaration of a variadic function uses an ellipsis as the last parameter,
e.g.intprintf(constchar*format, ...);
Seevariadic argumentsfor additional detail on the syntax and automatic argument conversions.
引數可變函式宣告時,最後一個 引數 使用 三個點好 來表示。
示例: int printf(const char * format, ... );
https://en.cppreference.com/w/c/language/variadic 裡面介紹 可變引數和 引數型別轉換。
引數型別轉換
1、對於沒有 函式原型 的函式的呼叫
2、對於 引數可變函式的呼叫(中的 可變引數部分),
這兩種情況下,傳遞進入的引數都會進行 隱式轉換
見 https://en.cppreference.com/w/c/language/conversion#Default_argument_promotions
Each argument of integer type undergoesinteger promotion
每個 integer 型別的引數都 轉換為int ; 每個 浮點 引數 都轉換為 double 型別。
int add_nums(int count, ...); int sum = add_nums(2, 'c', true); // add_nums is called with three ints: (2, 99, 1)
處理可變引數
macro 下面這幾個是 巨集定義
va_start
va_arg
va_end
va_copy c99 中引入
type 下面這個是 型別定義
va_list
使用示例
#include <stdio.h> #include <stdarg.h> void simple_printf(const char* fmt, ...) { va_list args; // va_list 定義一個 變數,用於存放 資訊 // va_start 巨集-第一個引數是 va_list 定義的變數,第二個引數是 函式 可變引數前面的一個引數。 // va_start 和 va_end 一一對應 va_start(args, fmt); while (*fmt != '\0') { if (*fmt == 'd') { int i = va_arg(args, int); // va_arg 第一個是 va_list 定義的變數,第二個是型別 printf("%d\n", i); } else if (*fmt == 'c') { // A 'char' variable will be promoted to 'int' // A character literal in C is already 'int' by itself int c = va_arg(args, int); printf("%c\n", c); } else if (*fmt == 'f') { double d = va_arg(args, double); printf("%f\n", d); } ++fmt; } va_end(args); // va_end 巨集只需要一個引數 } int main(void) { simple_printf("dcff", 3, 'a', 1.999, 42.5); }
va_copy 示例 - 求標準差
void va_copy(va_list dest, va_list src);
Theva_copy
macro copiessrc
todest
.
va_endshould be called ondest
before the function returns or any subsequent re-initialization ofdest
(via calls tova_startorva_copy).
#include <stdio.h> #include <stdarg.h> #include <math.h> double sample_stddev(int count, ...) { /* Compute the mean with args1. */ double sum = 0; va_list args1; va_start(args1, count); va_list args2; va_copy(args2, args1); /* copy va_list object */ for (int i = 0; i < count; ++i) { double num = va_arg(args1, double); sum += num; } va_end(args1); double mean = sum / count; /* Compute standard deviation with args2 and mean. */ double sum_sq_diff = 0; for (int i = 0; i < count; ++i) { double num = va_arg(args2, double); sum_sq_diff += (num-mean) * (num-mean); } va_end(args2); return sqrt(sum_sq_diff / count); } int main(void) { printf("%f\n", sample_stddev(4, 25.0, 27.3, 26.9, 25.7)); }