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 类型。
1 2 | 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
使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #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)); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具