在宏定义中,fmt是一个占位符,用于表示格式字符串。fmt可以是一个字符串字面量,也可以是一个参数。
而##__VA_ARGS__是一个可变参数宏定义的特殊标记,用于表示可变数量的额外参数。##是连接符,用于将前面的内容和后面的额外参数连接起来。
举例:
#include <stdio.h>#define PRINT_MESSAGE(fmt, ...) printf(fmt, ##__VA_ARGS__)int main() {int num1 = 10;int num2 = 20;float price = 5.99;char name[] = "John";PRINT_MESSAGE("Number1: %d Number2 :%d\n", num1,num2);PRINT_MESSAGE("The price is %.2f\n", price);PRINT_MESSAGE("Name: %s\n", name);return 0;
}
关于格式化字符串:
 printf 函数的第一个参数就是格式字符串。例如,上面的Number1: %d Number2 :%d\n
关于…和__VA_ARGS__
- … 是在函数或宏的参数列表中使用,表示该函数或宏可以接受可变数量的参数。它用于声明函数或宏的参数,并将实际传递的参数列表与之匹配。注意,... 它不能在宏的展开中使用。
- ##VA_ARGS 是在宏定义中使用的特殊标记,用于表示可变参数的展开。它用于展开可变参数,并将展开后的参数列表与其前面的内容连接起来。## 是连接符,用于在没有额外参数时确保宏定义仍然有效。
在上面的示例中,… 是宏定义中的参数,表示宏可以接受可变数量的参数(例如,fmt 后面的参数)。而 ##VA_ARGS 是宏定义中的展开语法,用于将前面的内容和可变参数展开连接起来。通过使用 ##VA_ARGS,即使没有额外的参数传递给宏,宏定义仍然有效。
利用宏进行log分级的代码展示:
#include <stdio.h>#define ERROR 1
#define INFO 2#define logLevel(Group, fmt, ...) \
do {                             \switch (Group) {              \case ERROR:              \printf("ERROR: ");   \break;               \case INFO:               \printf("INFO: ");    \break;               \default:                 \printf("unknown ");   \}                            \printf(fmt, ##__VA_ARGS__);  \
} while (0)           int main() {logLevel(ERROR, "Something went wrong.\n");logLevel(INFO, "Information message: %s\n", "Details");logLevel(3, "Something went wrong.\n");return 0;
}
打印:
ERROR: Something went wrong.
INFO: Information message: Details
unknown Something went wrong.