不定参数函数实现var_arg系列的宏 电驴的源码日志模块有一个叫 DebugLogError 函数,其签名如下:
//代码位于easyMule-master/src/WorkLayer/Log.h 55行 void DebugLogError(LPCTSTR pszLine, ...); 电驴的源码可以在公众号【 高性能服务器开发 】后台回复“获取电驴源码”即可获取。
这个函数的申明在 Log.h 头文件中,是一个全局函数,其实现代码在 Log.cpp 文件中:
//代码位于easyMule-master/src/WorkLayer/Log.cpp 111行 void DebugLogError(LPCTSTR pszFmt, ...) { va_list argp; va_start(argp, pszFmt); LogV(LOG_DEBUG | LOG_ERROR, pszFmt, argp); va_end(argp); } 这个函数是一个具有不定参数的函数(也就是参数个数不确定),比如调用这个函数我们可以传入一个参数,也可以传入二个或者三个参数等等:
DebugLogError(L"我喜欢你!"); DebugLogError(L"我喜欢你!", L"你喜欢谁?"); DebugLogError(L"我喜欢你!", L"你喜欢谁?", L"萧雨萌!"); 与此类似, C 语言中最熟悉的函数 printf() 和 scanf() 就是能传入不定参数的函数的例子,可是你知道如何编写这样具有不定参数的函数么?
你可以通过这段代码学习到编写方法,奥秘就在DebugLogError()中使用的几个你从来没见过的宏,让我们欢迎它们:
va_list va_start va_end 这几个宏是C函数库提供的,位于头文件stdarg.h中。下面我们利用这几个宏自定义一个ShowLove()函数:
#include <stdio.h> #include <tchar.h> #include <stdarg.h> #include <locale.h> int ShowLove(wchar_t* szFirstSentence, ...) { //用来统计可变参数数量 int num = 0; //第一步: //申明一个va_list类型对象ap,用于对参数进行遍历 va_list ap; //第二步: //使用va_start对变量进行初始化 //这里需要注意的是: //在传统C语言中,va_start把ap中内部指针设置为传递给函数参数的【第一个实参】; //而在标准的C中,va_start接受一个额外参数,也就是最后一个【固定参数】的名称, //并把ap中的内部指针设置为传递给函数的第一个【可变参数】. //所以你在VC++ 6.0和VS2008等高版本的编译器中使用va_start需要注意区别 //这里使用标准C va_start(ap, szFirstSentence); //第三步: //使用va_arg宏返回实参列表中的下一个参数值,并把ap的内部指针推向下一个参数(如果有的话) //必须指定下一个参数的类型。 //在调用va_start之后第一次调用va_arg将返回第一个可变参数的值 wprintf(szFirstSentence); wchar_t* p = 0; while(p = va_arg(ap, wchar_t*)) { wprintf(L"%s", p); num ++; } //第四步: //待所有可变参数都读取完毕以后,调用va_end宏对ap和va_list做必要的清理工作 va_end(ap); return num; } int main(int argc, char* argv[]) { setlocale(LC_ALL, ""); int z = ShowLoveL"我喜欢你!\n"); int y = ShowLove(L"我喜欢你!", L"你喜欢谁?\n"); int l = ShowLove(L"我喜欢你!", L"你喜欢谁?", L"萧雨萌!\n"); printf("可变参数个数依次是:%d\t%d\t%d\n", z, y, l); return 0; } 上述代码的运行结果是:...