有人问我,为什么这段代码产生一个随机数:
double a = 75.0;
printf("%d\n", a);
Run Code Online (Sandbox Code Playgroud)
我认为原因是4个字节double被解释为整数,但每次运行程序时打印值都不同.所以我开始尝试更多的东西,发现这个:
printf("%d\n", 75.0, 6);
Run Code Online (Sandbox Code Playgroud)
实际上打印出6号.所以我认为编译器试图修复参数,使它们匹配格式字符串,但后来我尝试了这个:
const char *formats[] = { "%d %.1f\n", "%.1f %d\n" };
int whichFormat = 0;
scanf("%d", &whichFormat);
printf(formats[whichFormat&1], 2.5, 7, 1.2);
Run Code Online (Sandbox Code Playgroud)
格式化字符串现在甚至在编译时都不知道,但它仍然以某种方式设法将参数类型与格式化字符串匹配,打印7 2.5或2.5 7根据输入.最后一个值(1.2)未打印.
所有这些都可以在compileonline.com上复制,它声称使用的是GNU GCC 4.8.1.
这里发生了什么?
未定义的行为正在进行中.
这种行为是不确定的,因此很难推理,也有点无意义的做实验,因为不能保证行为对于相同的输入保持相同(即明确定义).毕竟,这种行为是未定义的.
例如,第一个示例可能从一个寄存器读取预期的整数参数,而实际的浮点参数在另一个寄存器中.我不是说这是任何已知机器上发生的事情,但它可能就是这样.