我遇到了以下代码:
#define ERROR 0
#define WARN 1
#define INFO 2
#define DEBUG 3
extern int log_level;
char const *LEVEL_TO_STRING[] = { "ERROR", "WARN", "INFO", "DEBUG" };
#define LOG(level, s, ...) \
do \
{ \
if(level <= log_level) \
printf( "[%s] " s "\n", LEVEL_TO_STRING[level], ##__VA_ARGS__) \
} \
while(0) \
我不明白s
声明中printf
在引号之外做了什么。我试着搜索它是什么以及它是如何工作的,但我不确定要寻找什么。有人可以向我解释这段代码是如何工作的吗?
作为后续工作,是否可以在宏外部编写如上例所示的代码?我见过的最接近的是使用格式说明符:
#define FORMAT "ld"
long num = 1000000;
printf("%" FORMAT "\n", num);
这将有助于理解这两个案例如何在内部工作,以及为什么C不允许我像上面的宏中那样做printf("%s" s "\n", string1, string2)
之类的事情。
编辑:不是How does concatenation of two string literals work?的干净重复,因为这篇文章特定于printf(和格式说明符),因为它与宏有关。此外,在这篇文章的回复中有一些有用的信息在另一篇文章中没有。
答案 0 :(得分:3)
我不明白在printf语句的引号之外s是做什么的
为了了解会发生什么,您需要回忆一下s
被替换为程序文本中LOG
宏的第二个参数。这可行的唯一方法是s
是字符串文字,因为C合并它们。换句话说,
"quick brown fox"
和
"quick" " brown " "fox"
这两种写字符串文字的形式是等价的。
以同样的方式,将"ld"
传递给<{p>中的FORMAT
printf("%" FORMAT "\n", num);
相当于
printf("%ld\n", num);
并且是合法的。
为什么C不允许我像上面的宏那样做
printf("%s" s "\n", string1, string2)
之类的事情?
传递字符串文字以外的任何内容都是非法的:
char FORMAT[] = "ld";
printf("%" FORMAT "\n", num); // <<== Does not compile
代码中的 s
和FORMAT
必须不仅仅是字符串,而是字符串文字:
#define s "[%s]"
...
printf("%s" s "\n", string1, string2); // This compiles
答案 1 :(得分:1)
"[%s] " s "\n"
将s
定义为宏时,即使用#define
将所有内容连接在一起。
由于在预处理期间发生替换,因此不会将其标记为错误。在所有其他情况下,您应该收到语法错误。
答案 2 :(得分:0)
关键是线路延续&#39; \&#39;在定义的最后。该代码定义了一个宏函数LOG
,它执行指定的日志记录。
显然,宏的用户可以在s
中指定自己的格式化字符串,并在...
- &gt;中提供参数。 ##__VA_ARGS_