文章目录
- Intro
- 语法测试
- 依赖库
- 新函数使用测试:遍历并打印不定参数中的值
- 用两种方式封装函数:对多个int值求和
- 总结
Intro
有一天看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是多少。
- 注意不定参数的类型匹配。