C/C++可变参数函数

C 可变参数

typedef char* va_list;
void va_start ( va_list ap, prev_param );
type va_arg ( va_list ap, type ); 
void va_end ( va_list ap );


// 32位机器对int大小向上取整,64位机器对int64大小向上取整,因为参数在栈中传递都要对齐
#define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

#define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )

#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

#define va_end(ap) ( ap = (va_list)0 ) 

一个简单的例子

#include<stdio.h>
#include<stdlib.h>
#include<stdarg.h>
void funcarg(int n, ...){
    int t;
    va_list arg;
    va_start(arg, n);
    for(int i=0;i<n;i++){
        t = va_arg(arg, int);
        printf("%d ",t);
    } 
    va_end(arg);
}
int main()
{
    funcarg(3,1,2,3);
}

缺点:无法判断参数类型,只能用事先约定好的类型来取值,如果取值类型不对,会出现未知错误。

C++ initializer_list

使用initializer_list可以传递任意多个同类型的参数,类似于vector,是一种模板容器,可以将多个同类型参数打包成一个参数对象,然后传递给函数。

void funcinitial(initializer_list<int> ls){
    for(auto x:ls) cout<<x<<" ";
}

缺点:只支持单一类型,只读不写。

C++ 可变参数模板

接受可变参数的模板函数,可变参数称为参数包,包括模板参数包和函数参数包。
编译器从实参推断模板参数类型,并推断参数数目,然后实例化不同版本。
注意需要另外定义非可变参数的版本,负责终止递归。

template<typename T>
void funcvartemplate(T t){
    cout<<t<<" ";
}
template<typename T,typename ... Args>
void funcvartemplate(T t, Args ... args){  // 扩展Args
    cout<<t<<" ";
    funcvartemplate(args...);              // 扩展args
}

包扩展,就是将包分解为构成元素,对每个元素应用模式,获得扩展后的列表。
对于上面的例子,第一个扩展操作为扩展模板参数包,为print生成函数参数列表,第二个扩展在对print的调用中,为print生成实参列表。

posted @   trashwin  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示