C/C++不定参数的使用

前言

最近在写有关日志的demo,自己造了轮子,感觉自己实现的不是很好,实现的是一个定参数的日志输出,包括时间、日志等级、进程id、源文件名等必要的信息,但这种固定的格式扩展性不是很好,又了解到一些不定参数的使用,今天写一下文章记录一下。

C语言风格不定参数使用

基本格式

宏定义格式

#define LOG(fmt, ...)printf("/*指定输出格式*/" fmt,/*指定打印参数*/,__FILE__,__LINE__,##__VA_ARGS__)

下面让我来解释一下:

fmt是宏的第一个参数,表示格式化字符串(format string),就像 printf("Hello %s", name) 中的 "Hello %s"

C语言中不定参数使用...来代替,传递的参数会传递给printf处理。

__FILE__,__LINE__都是预处理部宏,表示源文件名和行号,如果不想输出可以不加

__VA_ARGS__是一个预处理宏,用于处理可变参数,前面的##是为了处理没有传递多参数时多余的逗号,例如如果只传递一个参数,调用就会被替换成下面这种格式

//调用
LOG("hello");

//不加##上面的调用会被替换成
printf("[%s:%d]hello\n", __FILE__, __LINE__, );
//__LINE__的后面多了一个逗号,编译器就会报错,加了##后逗号就可以被正确处理了

必要的头文件

只需要包含下面这个头文件即可

#include <stdarg.h>

现在我们比编写一个函数来试验一下

这个函数可以接受多个参数,count代表打印多少个数据,后面又count个要打印的数,PrintNum(5,1,2,3,4,5)的调用结果为

argument[0]:1
argument[1]:2
argument[2]:3
argument[3]:4
argument[4]:5

 #define _GNU_SOURCE是glibc中的一个宏定义,如果要使用va_list不仅要包含头文件还需要包含此宏定义
va_list是一个可变参数列表,他提供了一些方法访问未指定数量和类型的参数

最后使用完一定要调用va_end将定义的可变参数列表指针ap指向的资源释放,保持一个良好的编程习惯

#define _GNU_SOURCE
void PrintNum(int count,...)
{
    va_list ap;
    //第二个参数传可变参数列表前的最后一个参数
    va_start(ap,count);
    for(int i=0;i<count;i++)
    {
        int num=va_arg(ap,int);//修改ap指针来返回下一个参数
        printf("argument[%d]:%d\n",i,num);
    }
    va_end(ap);//将ap指针置为空
}

 

C++风格不定参数使用:

C++11引入了变参模板(template<typename... Args>),使得我们能够创建接受不定个数模板参数的模板。

基本语法

template<typename T,typename ...Args>

T代表一个任意类型的参数,...Args代表可变参数

下面我们使用这个模板来实现C++的可变参数

void Printf()
{
    std::cout<<std::endl;
}
template<typename T,typename ...Args>
void Printf(const T& v,Args && ...args)
{
    std::cout<<v;
    if(sizeof ...(args)>0)
    {
        Printf(std::forward<Args>(args)...);
    }
    else
    {
        Printf();
    }
}
​
Printf("你好");
Printf("你好","你好");
Printf("你好","你好",789);

​

这个函数接收任意类型的参数和一个右值引用的可变参数包,使用递归来输出可变参数,由于编译器参数推导到最后是没有参数的,我们还需要自定义一个无参函数来确保程序能够正确运行

上面这段代码会输出下面这些内容

你好
你好你好
你好你好789

如果你编写代码的c++版本更高(c++17),你可以使用下面这段代码简化操作

template<typename... Args>
void Printf(Args&&... args) {
    (std::cout << ... << args) << std::endl;
}

如果觉得文章写的还不错的话,请点个赞吧,如果有写的不对的地方,还请指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值