C语言如何实现C++的默认参数方法
前言在C里在声明一个函数时可以显示给参数指定默认参数值voidadd(inta,intb2)这样你直接调用add(1)编译器在构建的时候会默认给第二个参数传递2但是C语言没有这样的能力C语言是一个面向底层的语言它不具备那么多花里胡哨的特性但是我们可以通过宏的方法来实现C语言里宏给我们提供了极大的灵活性开发特别是在Linux、Zephyr这样的操作系统里经常会使用到宏来包装实现API。宏的可变参数计算方法我记得很久之前我看到过Zephyr的一段源码它为unit test提供的一套API是经过宏包装的主要功能是通过宏来指定数量来生成指定数量级的测试函数例如一个宏展3个Test函数不需要自己去手写多个其目的是为了测试一个API传递多个递阶数所以这里先讲解一下如何利用宏来实现可变参数计算方法。首先可以先看一段代码这段代码是我最近为项目设计的日志模块所编写的这里我简化了一下它的实现目的是为了教学如何通过宏计算可变参数#defineFAST_LOG_PRINT_NUMBER(_0,_1,_2,_3,_4,_n,...)_n#defineFAST_LOG_MERG(...)FAST_LOG_PRINT_NUMBER(_,##__VA_ARGS__,\4,3,2,1,0)#defineFAST_LOG_CART_TRUE(a,b)a##b#defineFAST_LOG_CART(a,b)FAST_LOG_CART_TRUE(a,b)#defineFAST_LOG_PRINT(...)FAST_LOG_CART(FAST_LOG_PRINT_,\FAST_LOG_MERG(__VAR_ARGS__))(__VAR_ARGS__)#defineFAST_LOG_PRINT_0()//0#defineFAST_LOG_PRINT_1(_1)//1#defineFAST_LOG_PRINT_2(_1,_2)//2#defineFAST_LOG_PRINT_3(_1,_2,_3)//3#defineFAST_LOG_PRINT_4(_1,_2,_3,_4)//4这个宏计算最大支持4个参数传递同时也支持传递空参数那么接下来来说一下这一段的实现原理其核心函数就两个FAST_LOG_PRINT_NUMBER(_0,_1,_2,_3,_4,_n,...)_nFAST_LOG_MERG(...)FAST_LOG_PRINT_NUMBER(_,##__VA_ARGS__,\4,3,2,1,0)FAST_LOG_MERG输入的是可变参数然后将__VA_ARGS__传递给FAST_LOG_PRINT_NUMBER这个函数是推导宏推导出有几个参数然后决定使用哪个FAST_LOG_PRINT这里推导的思路也非常简单FAST_LOG_MERG最终只输出_n而FAST_LOG_MERG在调用FAST_LOG_PRINT_NUMBER的时候假如给的是FAST_LOG_PRINT_NUMBER(0, 1, 2)那么最终宏翻译就是FAST_LOG_PRINT_NUMBER(_, 0, 1, 2, 4, 3, 2) 2最终这里的_n就变成了2这里其实就是利用一个巧妙的挤数字方法因为FAST_LOG_PRINT_NUMBER里面__VA_ARGS__后面紧跟着顺序数字依次递减当__VA_ARGS__参数越多后面的数字递增到N的就越大这样就能计算出到底有多少个参数了。其中最前面的__这个是为了解决0参数时候也就是调用宏不给参数时默认给一个0让_n这个数字变为0。那么通过这个实现我们就可以实现给默认缺省参数了在FAST_LOG_PRINT_0、FAST_LOG_PRINT_1、FAST_LOG_PRINT_2调用不同函数时来依次传递不同参数例如有一个set_sys_config的api可以封装为:FAST_LOG_PRINT_0() set_sys_config(a, b, c, d)#define FAST_LOG_PRINT_1(_1) set_sys_config(_1, a, b, c)在调用时只需要调用FAST_LOG_PRINT即可FAST_LOG_PRINT(); //无参数FAST_LOG_PRINT(“hello world”); //1个参数这样就实现类似c的缺省参数其实这个方法在Linux/zephyr里也有用过不过不是用于缺省缺省只是这种开发方法应用场景的其中一个在内核里多数用于例如写test case要写许多非常多的重复代码那么这个时候就可以利用这种方法来动态生成不同参数级别的test case func。

相关新闻

最新新闻

日新闻

周新闻

月新闻