C语言中不定参数 ... 的语法以及函数封装
锦天 人气:0Intro
有一天看C代码看到某个方法有这样的定义:在函数形参列表处,有...
的写法,就像Java中的不定参数那样。
如:
int printf(const char * __restrict, ...) __printflike(1, 2); int scanf(const char * __restrict, ...) __scanflike(1, 2);
那么C语言中的不定参数特性,是怎样使用的呢,以及我们如何利用该特性,封装自己的函数?
语法测试
依赖库
需要用到 stdarg.h
中的三个函数:
#define va_start(ap, param) __builtin_va_start(ap, param) #define va_end(ap) __builtin_va_end(ap) #define va_arg(ap, type) __builtin_va_arg(ap, type)
新函数使用测试:遍历并打印不定参数中的值
主要是测试一下上面提到的三个库函数的使用。
#include <stdio.h> #include <stdarg.h> // 声明列表的结束值 #define ARGUMENTS_END_VALUE -1 void printMultiArgs(int firstArgs, ...) { // 声明参数列表的变量 va_list ap; // 初始化参数列表 va_start(ap, firstArgs); printf("%d\n", firstArgs); int currValue; while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) { printf("%d\n", currValue); } // 结束参数列表 va_end(ap); } int main(int argc, const char * argv[]) { printMultiArgs(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE); return 0; }
用两种方式封装函数:对多个int值求和
// // main.c // C不定参数 // // Created by wuyujin1997 on 2023/1/23. // //#define va_start(ap, param) __builtin_va_start(ap, param) //#define va_end(ap) __builtin_va_end(ap) //#define va_arg(ap, type) __builtin_va_arg(ap, type) #include <stdio.h> #include <stdarg.h> // 声明列表的结束值 #define ARGUMENTS_END_VALUE -1 void printMultiArgs(int firstArgs, ...) { // 声明参数列表的变量 va_list ap; // 初始化参数列表 va_start(ap, firstArgs); printf("%d\n", firstArgs); int currValue; while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) { printf("%d\n", currValue); } // 结束参数列表 va_end(ap); } /// 对多个int变量求和(需要提前约定好参数结束的标志值 ARGUMENTS_END_VALUE) /// - Parameter firstArgs: <#firstArgs description#> int sum1(int firstArgs, ...) { int result = 0; va_list ap; va_start(ap, firstArgs); result+= firstArgs; // 手动处理第一个参数 int currValue; while ((currValue = va_arg(ap, int)) != ARGUMENTS_END_VALUE) { result += currValue; } va_end(ap); return result; } /// 对多个int变量求和(需要主动本方法:不定参数的个数是多少) /// - Parameters: /// - count: 不定参数的个数 /// - firstArgs: 第一个参数,显式的形参 int sum2(int count, int firstArgs, ...) { int result = 0; va_list ap; va_start(ap, firstArgs); result += firstArgs; for (int i = 1; i < count; i++) { int currValue = va_arg(ap, int); // printf("%d %d\n", i, currValue); result += currValue; } va_end(ap); return result; } int main(int argc, const char * argv[]) { printMultiArgs(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE); printf("sum1 %d\n", sum1(1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE)); int LENGTH = 9; printf("sum2 %d\n", sum2(LENGTH, 1,2,3,4,5,6,7,8,9, ARGUMENTS_END_VALUE)); return 0; }
执行结果:
总结
- 需要引入头文件 #include <stdarg.h>
- 一个新类型,三个新函数
- 类型 va_list
- 函数,其中 ap 为 va_list 类型的变量。
- va_start(ap, param) param为不定参数列表的第一个参数。
- va_arg(ap, type) 不定参数中变量的类型吗,如int, short, long 等。
- va_end(ap)
- 如何确定 va_arg 的size/有多少个元素? 没有原生的属性/变量可以告诉我们。
- 约定一个值作为 end_value ,而且要保证:这个值不会出现在传入的多个参数值中。
- 在咱自己封装的函数中,新增一个参数用于告知被调函数内部:本次不定参数的size是多少。
- 注意不定参数的类型匹配。
总结
加载全部内容