前言

自定义函数的形式和大致参数已经明确,然后就是返回指针和引用之类的.


头文件

  • cstdarg

正文

main函数的参数虽然也可以叫不定量,但是毕竟是提前规定了的。


1
2
3
int Add(unsigned count, ...){

}

比如实现一串不定量的数字求和,后面的参数就可以用…这种写法,但是必须要知道个数
虽然后面用省略表示不定量,但是不是直接说就是数组了,函数里调用起来也挺稀奇的
不过越是稀奇古怪用到的就越少,毕竟实际上没有这么多不定量的场景

1
int x = Add(5,1,2,3,4,5);

调用的时候没啥特殊,但在实现部分中,如何调用...才是重点

1
2
3
int Add(unsigned count, ...){
va_list arg;
}

va_list其实就是一个char*类型的变量:
如果直接使用char* arg也无可厚非。

然后就是传递不定量的值,因为引用了cstdarg头文件,所以可以使用封装好的

1
2
3
4
int Add(unsigned count, ...){
va_list arg;
va_start(arg,count);
}

传递到指针之后,需要注意用什么类型去读取

1
2
3
4
5
int Add(unsigned count, ...){
va_list arg;
va_start(arg,count);
va_arg(arg, int);
}

va_arg的特点就是可以重复读取,毕竟每调用一次才能往后读取不定量参数
于是乎就可以写个for循环。

1
2
3
4
5
6
7
8
9
10
11
int Add(unsigned count, ...){
va_list arg;
va_start(arg,count);
int sum = 0;

for(int i{}; i<count; i++){
sum += va_arg(arg, int);
}

return sum;
}

同理int 类型的函数,别忘了返回值。

然后还要特别注意,因为va_list是一个指针,虽然函数声明周期结束变量可能会被回收,但是肯定是有人为的方式去消除

1
2
3
4
5
6
7
8
9
10
11
12
int Add(unsigned count, ...){
va_list arg;
va_start(arg,count);
int sum = 0;

for(int i{}; i<count; i++){
sum += va_arg(arg, int);
}

va_end(arg);
return sum;
}

那就是va_end(); 用完记得手动释放吧。

最后在main接收返回值并打印

当然如果说都是一种类型,显然单纯的for循环不是更快
所以不定量的含义同时也包含了不同类型的参数时,不过在va_arg的时候你需要合理的控制读取的类型,可能也稍显2b,毕竟也挺麻烦


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int Add(unsigned count, ...){
va_list arg;
va_start(arg,count);
std::cout << &arg << std::endl;
int sum = 0;

for(int i{}; i < count; i++){
printf("arg累加前:%p\n",arg);
//也可以用std::cout << std::hex << (int)arg;但是感觉C语言这种格式化输出在这里更方便。
sum += va_arg(arg, int);
}

va_end(arg);

return sum;
}

简单的打印一下循环开始前arg的地址和每一次变化后地址。
不难看出地址每次增加的4其实就是跟变量类型有关。


你说自己实现类似的功能也不难,但是要规避其它风险的时候设计起来就蹑手蹑脚了,所以说有一些标准需要委员会去发布。


结语

白天上课刷手机,下午晚上有空打游戏,大半夜回头补补也是没谁了~