可变参数宏函数
可变参数宏函数是一种在预处理阶段展开的可变参数的宏定义。它允许在宏中使用可变数量的参数,并对这些参数进行操作或生成相应的代码。
定义可变参数宏函数
要定义可变参数宏函数,可以使用#define
指令和特殊的宏定义语法。下面是定义可变参数宏函数的通用语法:
#define LOG(...) macro_body
LOG
:宏函数的名称。...
:省略号表示可变数量的参数。macro_body
:宏函数的具体代码。
使用可变参数宏函数
在使用可变参数宏函数时,可以像调用普通函数一样使用它。参数的数量和类型可以根据需要进行变化。
示例
#include <stdio.h>
#define LOG(...) printf(__VA_ARGS__)
int main() {
LOG("This is a log message.\n");
LOG("The sum of %d and %d is %d.\n", 5, 3, 5 + 3);
return 0;
}
在上述示例中定义了一个名为LOG
的可变参数宏函数。它使用了...
来表示可变数量的参数。在宏定义中,我们使用了printf
函数来输出日志信息。通过将参数__VA_ARGS__
传递给printf
函数,可以将可变参数传递给宏函数,并在展开时替换为对应的值。
在main
函数中,我们使用LOG
宏函数来输出日志信息。第一次调用中,只有一个参数作为日志消息,而第二次调用中,除了日志消息外,还有三个参数用于计算并输出求和结果。
特殊用法
当需要在可变参数的前面添加一个格式字符串参数时,需要使用以下方式来定义和使用可变参数宏函数:
#include <stdio.h>
//此处的format是一个命名参数
#define LOG(format, ...) printf("[%s-%d]:"format,__FILE__,__LINE__,__VA_ARGS__)
int main() {
LOG("The number is %d.\n", 10);
LOG("Hello, %s!\n", "Alice");
return 0;
}
在上述示例中定义了一个名为 LOG
的宏函数,它具有一个额外的 format
参数用于指定格式字符串。在宏定义中,我们使用 printf
函数来输出日志信息。"[%s-%d]:"
是一个格式化字符串,它包含了文件名和行号信息,__FILE__
和 __LINE__
是预定义的宏,它们分别表示当前文件名和行号.然后,我们将 format
参数与可变参数 __VA_ARGS__
分别传入LOG中。这样,我们可以在展开宏函数时将 format
参数和可变参数传递给 printf
函数。
在 main
函数中,我们使用 LOG
宏函数来输出日志信息。每次调用宏函数时,我们提供一个格式字符串作为第一个参数对应format
,然后根据格式字符串中的占位符提供相应的参数。
输出:
这种方式就允许了在可变参数宏函数中添加一个格式字符串参数,以便更灵活地控制输出的格式。
在gcc编译器下,如果调用语句没有给可变参数是会报错的:
#include <stdio.h>
#define LOG(format, ...) printf("[%s-%d]:"format,__FILE__,__LINE__,__VA_ARGS__)//错误代码
int main() {
LOG("hello\n");//这里没有了可变参数
return 0;
}
报错:
因为在__LINE__
后面还有一个逗号,而此时可变参数为空,则宏替换时调用处变成了printf("[a.c-9]:""hello",__FILE__,__LINE__,)
,多了一个逗号,所以会报错。
解决方案
#include <stdio.h>
#define LOG(format, ...) printf("[%s-%d]:"format,__FILE__,__LINE__,##__VA_ARGS__)//正确
int main() {
LOG("hello\n");//这里没有了可变参数
return 0;
}
//C语言提供了##号,在`__VA_ARGS__`前加上双井号就可以解决没有可变参数的问题。
输出: