【C/C++】 变参函数
#include <stdio.h> #include <stdbool.h> #include <stdarg.h> #define MLA_ASSERT(expr) (int)((!!(expr)) && (printf("assert fail: \"%s\" @ %s, %u", #expr, __FILE__, __LINE__), printf("\r\n"), Abort())) int Abort(void) { printf("reset reboot!\n"); // 重启代码 } /** * 按自定义格式符解析数据 */ void process(const char *fmt, va_list args) { CHECK(fmt != NULL); for (; *fmt; fmt++) { if (*fmt == '%') { switch (*++fmt) { case 'a': case 's': { char *str = va_arg(args, char *); printf("%s", str); continue; } case 'b': { float *num = va_arg(args, float *); printf("%f", *num); continue; } case 'f': { float num = va_arg(args, double); // 解析浮点数须用double,不能用float printf("%f", num); continue; } default: printf("%c", *fmt); continue; } } else { printf("%c", *fmt); } } } /** * 自定义可变参数函数 * @param hint: 传递给函数的额外参数 * @param fmt: 自定义格式符 */ void VariadicFunction(char *hint, const char *fmt, ...) { MLA_ASSERT(hint == NULL); MLA_ASSERT(fmt == NULL); // 定义一个参数列表 va_list args; // 初始化列表参数args,第二个参数是可变参数前的第一个固定参数,即省略号前的第一个参数 va_start(args, fmt); // 解析数据 process(fmt, args); // 释放可变参数列表 va_end(args); // 额外参数处理 printf("%s, hint: %s\n", __func__, hint); } /** * 带缺省参数可变参数函数 * @param hint: 传递给函数的额外参数 * @param isPrint: 带缺省属性的参数 * @param number: 带缺省属性的参数 * * @note 带缺省属性的参数得从右边开始,函数声明时不能带缺省值 */ void DefaultVariadicFunction(char *hint, bool isPrint = false, int number = 666) { MLA_ASSERT(hint == NULL); printf("%s, hint: %s\n", __func__, hint); if (isPrint) { printf("%s, This is a function with default arguments: %d\n", __func__, number); } } void PackageFormattingData(char *hint, const char *fmt, ...) { MLA_ASSERT(hint == NULL); MLA_ASSERT(fmt == NULL); char buf[256] = { 0 }; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printf("%s, hint: %s\n", __func__, hint); // file_write(buf); printf("%s, content: %s\n", __func__, buf); } int main() { float f = 6.66; VariadicFunction("Here's a hint!", "%a%b%f%a", "string1", &f, 9.99, "STRING2"); DefaultVariadicFunction("Here's a hint!"); DefaultVariadicFunction("Here's a hint!", true); DefaultVariadicFunction("Here's a hint!", true, 999); PackageFormattingData("Can be used for writing files!", "%d, %f, %c, %s", 666, 88.88, 'C', __func__); PackageFormattingData("Can be used for writing files!", "%c, %s", 'F', "You can refer to the use of files as logs on the back end."); return 0; }
自定义变参函数需要加入参数格式检查,以便在编译期就发现问题,避免运行时参数问题导致的异常
Function Attributes - Using the GNU Compiler Collection (GCC)
void __attribute__((format(printf,2,3))) VariadicFunction(char *hint, const char *fmt, ...) { MLA_ASSERT(hint == NULL); MLA_ASSERT(fmt == NULL); // 定义有个参数列表 va_list args; // 初始化列表参数args,第二个参数可变参数前的第一个固定参数,即略号前的第一个参数 va_start(args, fmt); // 解析数据 process(fmt, args); // 释放可变参数列表 va_end(args); // 额外参数处理 printf("%s, hint: %s\n", __func__, hint); } VariadicFunction("Here's a hint!", "function name: %s");
加了参数格式化检查就会在编译时给出一个warning
再牛逼的梦想也架不住傻逼似的坚持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2018-04-24 串口数据字节位的理解