使用UB打印的宏功能

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)

demo1的

DEMO2

我很可能会遇到UB,但是挖掘N1570并没有给出明确的解释.我发现最接近这个的是5.1.1.2(p4):

执行预处理指令,扩展宏调用,并执行_Pragma一元运算符表达式.如果 通过标记连接(6.10.3.3)生成与通用字符名称的语法匹配的字符序列,则行为未定义.

可能令牌"1" "2"连接产生UB,但我不确定.

gsa*_*ras 6

可能令牌"1""2"连接在一起产生UB,但我不确定.

你是对的.

"1"和"2"变成了"12",并到所述第一%sprintf().然后,第二个%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");.


Lun*_*din 5

FOO扩展到printf("%s%s\n", "1" "2").字符串文字在预处理期间连接,产生printf("%s%s\n", "12").

这不是对printf和UB的正确调用.标准中的相关部分是:

7.21.6.1 fprintf函数
...
2 ...如果格式的参数不足,则行为未定义.

  • @SomeName是的.你引用的部分是完全不相关和随机的,它指的是使用`##`预处理标记连接的特殊情况 - 这是与字符串文字串联完全不同的东西 - 产生一个"通用字符名称",如`\U1234`.通用字符名称是一种奇特的罕见功能,允许在源编辑器不支持的情况下在源中键入字符.它在6.4.3中描述.它与你的问题无关. (2认同)