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. int printf(const char* format, ...);
See variadic arguments for 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 undergoes integer promotion (see below), and each argument of type float is implicitly converted to the type double
每个 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);
The va_copy
macro copies src
to dest
.
va_end should be called on dest
before the function returns or any subsequent re-initialization of dest
(via calls to va_start or va_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)); }