C语言-可变参数列表
起步
假使你有使用 Python 编程的经验,你应该会觉得设计接口能用 *arg
和 **kwarg
这件事是多么的酸爽。毕竟定义一个拥有长长参数列表的函数是多么的累赘,形参不能总是被函数使用到则是累赘中的累赘。多说无益,还是用个 Python Demo 举例。
假使我想设计一个打印函数,就叫 YouPrint 吧。YouPrint 会将我传递的参数按每行打印,且排头以 “You” 开头。使用如下:
Usage:
YouPrint("zhong", "ying", "ding")
Output:
You: zhong
You: ying
You: ding
如果不用“可变参数列表”的方式设计,那 YouPrint 应该如下这般:
def YouPrint(a, b, c):
for alpha in (a, b, c):
print(f"You: {alpha}")
这样显然在违背我们对 打印函数 的习惯。难道打印函数不应该允许任意传参吗?万一我只传一个参数呢,又或者传十个呢?在 Python 中,其解决办法就是 *arg
。因此合理的设计是:
def YouPrint(*arg):
for alpha in arg:
print(f"You: {alpha}")
在 Python 中,*变量名
出现在形参中时,其意义为:变量 arg (上面例子中用到 arg)会接收所有的位置传参(这些参数没有被其他形参接收),自身将以元组的身份出现,存放这些传递过来的参数。听不懂没关系,我就是想引出,C 语言也可以做到。
C语言的可变参数列表
C 语言的可变参数主要有三种方式实现,一种基于标准库 <stdarg.h>
,使用 va_start, va_arg, va_end。另一种用宏 __VA_ARGS__, 再一种用记号粘贴符号 ##。
后两种的使用场景较小,常在 debug 之类的时候用;第一种使用场景则更为广泛些,但事实上不建议滥用。
VA_ARGS 与 记号粘贴符
现在假设一个场景,我们写程序的时候需要 printf 之类的 DEBUG 操作,同时希望程序完成之后,这些打印语句会自动失效,而非我们手动去删除。并且,这些 DEBUG 语句应该要有明显的标识,足以让我们一眼辨出哪些是 DEBUG 语句,哪些是正常输出。
而作为一个输出函数,自然有必要同 printf 一样,在合法操作下传递任意个参数。
根据以上要求,显然宏函数最为合适不过。用 __VA_ARGS__ 实现如下:
#include