我有一个名为PRINT(...)
的宏,我在我的代码中使用它,它获取可变数量的参数,行为类似于printf
(获取格式和参数)。它的定义如下:
#define PRINT(...) PRINT(__VA_ARGS__)
现在我想修改它,以便它有一个可选参数,比如它的名字是number
,它会为打印添加一个数字前缀。例如:
PRINT("%s", "hi")
- >将打印hi
PRINT(1, "%s", "hi")
- >将打印1: hi
如何更改PRINT
宏以支持此功能?
重要的是,我不希望从我的代码中更改对此宏的任何现有调用(在示例中,如果我调用PRINT("%s", "hi")
- 它在更改后需要保持不变)。<登记/>
此外,我无法为此目的创建新的宏 - 必须使用现有的PRINT
宏来实现此目的(但当然我可以更改它的arguemnts定义)。
知道我该怎么办?
编辑:我看到这个post关于可变参数宏 - 但它与我在这里要求的不同,因为参数number
需要是一个公认的变量,它将在实现中被处理如果对PRINT
的调用不包含-1
参数(PRINT
将是打印无数字的指示符),则number
为-1
,否则将{}打印数字前缀。
答案 0 :(得分:2)
从C11开始,您可以使用_Generic
关键字。这允许您检查任何值或变量的类型。根据{{3}},_Generic
的行为因编译器而异。 this document使用This answer提供了一个简单的解决方案。
#define PRINT(fst, ...) \
( \
_Generic((0, fst), char *: 1, default: 0) ? \
PRINTNL(fst, __VA_ARGS__) : \
PRINTL(fst, __VA_ARGS__) \
)
PRINTNL
打印时没有数字,PRINTL
打印数字。
其余代码:
#define PRINTNL(...) printf(__VA_ARGS__)
#define PRINTL (n, ...) ({ \
printf("%d: ", n); \
printf(__VA_ARGS__); \
})
答案 1 :(得分:1)
由于您在撰写本文时已经知道第一个参数是否是数字前缀,因此请使用其他名称创建一个宏,以便为该数字添加前缀。在此,我假设PRINT(...)
扩展为printf(__VA_ARGS__)
:
#define PRINT(...) printf(__VA_ARGS__)
所以定义一个调用NPRINT
两次的宏printf
,一次用数字输出前缀,用格式输出一次:
#define NPRINT(number, fmt, ...) (printf("%d: ", number), printf(fmt, __VA_ARGS__))
用法
#include <stdio.h>
int main(void) {
NPRINT(1, "%s\n", "hi");
}
当然,如果对printf
的调用应该是 atomic ,那么这不起作用 - 现在如果格式字符串始终是 literal 字符串,然后你可以使用字符串连接:
#define NPRINT(number, fmt, ...) (printf("%d " fmt, number, __VA_ARGS__))
如果它可以是一个变量,并且只允许对PRINT
进行一次调用,那么我唯一可以看到的便携式方式就是创建一个构建格式的函数。
对于没有数字参数的最新编辑,-1:
应该加上前缀,这只会变成:
#define PRINT(...) NPRINT(-1, __VA_ARGS__)
答案 2 :(得分:0)
请查看##__VA_ARGS__
macro。还要检查下面为日志函数编写的代码。
在头文件中
/** #include <libgen.h> */
void APP_LOGX(const char * file, int num, const char* message, ...)
{
va_list ap;
int length;
char * tfilename = NULL;
tfilename = strdup(file);
length = strlen(message);
if(length>0){
va_start(ap, message);
vprintf(message, ap);
printf(" | File: %s Line %d ", basename(tfilename), num);
va_end(ap);
/* add newline if nessasary */
if(message[length -1] != '\n'){
printf("\n");
}
}
free(tfilename);
}
在实施中
APP_LOG("app display init")
申请
APP_LOG("Value of x acceleration %.2f", g);
APP_ERROR("Something bad happened!")
或
category_orders={'m4':d}