ZC:环境: Win7 x64(旗舰版),Microsoft Visual Studio 2010(版本 10.0.30319.1 RTMRel, Microsoft .NET Framework(版本 4.0.30319 RTMRel))
1、代码:
#include <stdio.h> #include <stdarg.h> #include <windows.h> int sum(int count, ...);//原型中使用省略号 // 函数的参数为:DWORD _dw, HWND _h, char* _pc void TextZ(int _n, ...)// ZC: 貌似无法动态获得参数的个数,∴只能在参数中带上参数的个数(需要的话),我一般放在可变参数前面的位置。 { va_list ap;//声明一个va_list变量 va_start(ap, _n);//初始化,第二个参数为最后一个确定的形参// ZC: 需要 参数个数 作为函数va_start(...)的参数 // ZC: 貌似参数只能依次取,不能随机取? DWORD dw = va_arg(ap, DWORD);//读取可变参数,的二个参数为可变参数的类型 HWND h = va_arg(ap, HWND); char* pc = va_arg(ap, char*); va_end(ap);//清理工作 // *** printf("DWORD : %d, HWND : %d, char* : %s ", dw, h, pc); } // 下面的函数 和 上面的函数 几乎一模一样,只是这里是使用 指针来取得可变参数,这里是尝试其可行性 void TextZ01(int _n, ...)// ZC: 貌似无法动态获得参数的个数,∴只能在参数中带上参数的个数(需要的话),我一般放在可变参数前面的位置。 { va_list ap;//声明一个va_list变量 va_start(ap, _n);//初始化,第二个参数为最后一个确定的形参// ZC: 需要 参数个数 作为函数va_start(...)的参数 // ZC: 貌似参数只能依次取,不能随机取? DWORD* pdw = &va_arg(ap, DWORD);//读取可变参数,的二个参数为可变参数的类型 HWND* ph = &va_arg(ap, HWND); char** ppc = &va_arg(ap, char*); va_end(ap);//清理工作 // *** printf("DWORD : %d, HWND : %d, char* : %s ", *pdw, *ph, *ppc); } void main() { //int i = sum(3, 4,5,6); //printf("sum : %d ", i); TextZ(3, 567, 30303030, "TextZ"); TextZ01(3, 567, 30303030, "TextZ"); system("pause"); } // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** int sum(int count, ...)//count 表示可变参数个数 { va_list ap;//声明一个va_list变量 va_start(ap, count);//初始化,第二个参数为最后一个确定的形参 int sum = 0; for(int i = 0; i < count; i++) sum += va_arg(ap, int);//读取可变参数,的二个参数为可变参数的类型 va_end(ap);//清理工作 return sum; }
2、控制台输出:
3、
4、自己的包装函数(1)
ZC:主要是在 函数内部去使用 sprintf_s(...) 来组合字符串,省的写在外面(写在外面 代码太多太乱 看不清晰)
ZC:下面,函数传入的可变参数 都是 DWORD类型的,如果需要 不同的类型的话,可以在可变参数中加入指定参数类型的参数,见下面的"5"
void ShowMsg_Thread_DLL_VA_DWORD(char* _pc, int _n, ...) { if (g_fnShowMsg_Thread == NULL) return; if (_n > 5) { ::MessageBoxA(0, "Parameter count not enough .", "ShowMsg_Thread_DLL_VA_DWORD", 0); return; } DWORD dws[16] = {0}; char buf[512] = {0}; va_list ap; va_start(ap, _n); if (_n == 0) g_fnShowMsg_Thread(_pc); else if (_n == 1) { dws[0] = va_arg(ap, DWORD); sprintf_s(buf, sizeof(buf), _pc, dws[0]); } else if (_n == 2) { for (int i=0; i<_n; i++) dws[0] = va_arg(ap, DWORD); sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1]); } else if (_n == 3) { for (int i=0; i<_n; i++) dws[0] = va_arg(ap, DWORD); sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2]); } else if (_n == 4) { for (int i=0; i<_n; i++) dws[0] = va_arg(ap, DWORD); sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2], dws[3]); } else if (_n == 5) { for (int i=0; i<_n; i++) dws[0] = va_arg(ap, DWORD); sprintf_s(buf, sizeof(buf), _pc, dws[0], dws[1], dws[2], dws[3], dws[4]); } va_end(ap); g_fnShowMsg_Thread(buf); }
5、自己的包装函数(2)
ZC:函数传入的可变参数,如果需要是 不同的类型的话,可以在可变参数中加入指定参数类型的参数,例如 我在 D?SvgExe的D?RemoteCall代码中的使用方式
6、
7、(20191112)Qt598x64(vs2017) 编译的"Widgets Application"中 printf(...)和fprintf(...)调用后,不会立即在控制台输出信息,需要调用"fflush(stdout);"后 信息才会显示出来,于是就想 封装一个信息打印的函数 在函数中直接调用 fflush(...),这就需要 封装成可变参数的函数,于是查了资料,封装成这样:
#include <stdarg.h> void MsgPrint(const char *format, ...) { va_list ap; int n; va_start(ap, format); n = vprintf(format, ap); va_end(ap); //return n; // ZC: 上面是 printf(...)的实现 fflush(stdout);// Qt598不执行这一句的话 print(...)和fprintf(stdout, ...)输出的信息 不会立即显示在"应用程序输出"中 }
(1)va_list 、va_start、 va_arg、 va_end 使用说明 - 土戈 - CSDN博客.html(https://blog.csdn.net/f110300641/article/details/83822290)
// 附:可变参数应用实例 // 1.printf实现 #include <stdarg.h> int printf(char *format, ...) { va_list ap; int n; va_start(ap, format); n = vprintf(format, ap); va_end(ap); return n; } // 2.定制错误打印函数error #include <stdio.h> #include <stdarg.h> void error(char *format, ...) { va_list ap; va_start(ap, format); fprintf(stderr, "Error: "); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, " "); return; }
8、
9、