Som*_*ame 1 c macros printf undefined-behavior
我正在学习如何使用宏函数,现在面临一些(很可能是未定义的)行为.这是一个例子:
#include <stdio.h>
#define FOO(a, b) { \
printf("%s%s\n", #a #b); \
} \
int main(int argc, char * argv[]){
{ printf("%s%s\n", 1 2); } //compile error
FOO(1, 2); //prints 12 with some garbage
}
Run Code Online (Sandbox Code Playgroud)
我很可能会遇到UB,但是挖掘N1570并没有给出明确的解释.我发现最接近这个的是5.1.1.2(p4):
执行预处理指令,扩展宏调用,并执行_Pragma一元运算符表达式.如果 通过标记连接(6.10.3.3)生成与通用字符名称的语法匹配的字符序列,则行为未定义.
可能令牌"1" "2"连接产生UB,但我不确定.
可能令牌"1""2"连接在一起产生UB,但我不确定.
你是对的.
"1"和"2"变成了"12",并到所述第一%s在printf().然后,第二个%s没有任何处理,因此垃圾值.
编译器警告也同意(当然):
prog.cc:4:12: warning: format '%s' expects a matching 'char*' argument [-Wformat=]
4 | printf("%s%s\n", #a #b); \
| ^~~~~~~~
prog.cc:9:5: note: in expansion of macro 'FOO'
9 | FOO(1, 2); //prints 12 with some garbage
| ^~~
prog.cc:4:16: note: format string is defined here
4 | printf("%s%s\n", #a #b); \
| ~^
| |
| char*
Run Code Online (Sandbox Code Playgroud)
在你的宏中,改变这个:
printf("%s%s\n", #a #b);
Run Code Online (Sandbox Code Playgroud)
对此:
printf("%s%s\n", #a, #b);
Run Code Online (Sandbox Code Playgroud)
正如@Blaze评论的那样,逗号会起作用. Live Demo
注意:对于硬编码的printf()工作调用,您希望生成1和2个字符串; 使用逗号是不够的.示例:printf("%s%s\n", "1", "2");.
FOO扩展到printf("%s%s\n", "1" "2").字符串文字在预处理期间连接,产生printf("%s%s\n", "12").
这不是对printf和UB的正确调用.标准中的相关部分是:
7.21.6.1 fprintf函数
...
2 ...如果格式的参数不足,则行为未定义.