可变参数在c语言里其实是非常常见的一种语法,相信每一个学过c语言,哪怕只上过一次机,学过没几课的人都遇到过。没见过?请看:
printf("Params list: %s, %s, %s, %d in all.", "P1", "P2", "P3", 3);
printf("Param 1: %s.", "P1");
printf函数便是可变参数函数的典型例子。前者它拥有5个参数,后者则只有2个。
可变参数函数的实现想必大家都有了解过,现仅举一例以兹说明。
void AppendAppLogEx(
BOOL bGetLastError, //是否获取系统错误代码BOOL bShowMessage, //是否显示系统错误信息BOOL bReportPos, //是否报告调用该函数的位置WCHAR *wcsFileName, WCHAR *wcsFuncName, int nLineNum, //该函数的位置信息const WCHAR *format, ... )//可变参数部分{va_list argptr;//Need get last error DWORD nErrorNo = 0;WCHAR wcsBuffer[2048] = {0,};if (bGetLastError){nErrorNo = GetLastError();FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nErrorNo,
LANG_NEUTRAL,
wcsBuffer,
MAX_PATH,
NULL);
if (bShowMessage)MessageBox(NULL, wcsBuffer, L"zinFrame Service Error", MB_OK);}// print to buffer
va_start(argptr,format);wcsBuffer[wcslen(wcsBuffer)]=L'\n';_vsnwprintf(wcsBuffer + wcslen(wcsBuffer), 2047-wcslen(wcsBuffer), format, argptr);wcsBuffer[wcslen(wcsBuffer)]=L'\n';wsprintf(wcsBuffer+wcslen(wcsBuffer), L"@%s(%d)<%s>", wcsFileName, nLineNum, wcsFuncName);WriteLogFile(wcsBuffer);va_end(argptr);}
这个函数实现了可变参数记录Log的功能。比如你可以这样调用:
AppendAppLogEx(TRUE, FALSE, TRUE, __FILE__, __FUNCTIONNAME__, __LINE__, L"Error while counting down from %d in device %s.", nCnt, wcsDevName);
也可以这样用:
AppendAppLogEx(TRUE, FALSE, FALSE, NULL, NULL, 0, L"Error accessing the device.");
他们的参数个数是不同的。
现在有一个问题,就是我们有时候需要参数三(bReportPos)来报告调用该函数的位置,以便程序员调试,有时候不需要,每次填这个比较麻烦。所以我们就想采用一个简短的办法,比如:
#define AppendAppPosLog(x,y,...) AppendAppLogEx(x, y, TRUE, __FILE__, __FUNCTIONNAME__, __LINE__, __VA_ARGS__)
#define AppendAppLog(x,y,...) AppendAppLogEx(x, y, FALSE, NULL, NULL, 0, __VA_ARGS__)
其中__VA_ARGS__为替换符(replacement identifier),表示了省略号代表的内容。
这样,我们看到,宏也可以使用可变参数。