【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
再牛逼的梦想也架不住傻逼似的坚持