源代码很简单,就是定义一个float变量a=2.5,int变量b=2
然后将a,b分别按%d %f型输出。
当然没有按正确类型格式化输出肯定是有问题的。
但是按正确类型格式化输出也发生了很奇怪的问题。
源代码如下,VS2013下编译通过0 errors, 0 warnings。
#include <stdio.h>
int main(void)
{
float a = 2.5;
int b = 2;
printf("%d\n%f\n%d\n%f\n", a, a, b, b); /*这条语句的输出全是错的*/
putchar('\n');
printf("%f\n%d\n%f\n%d\n", a, a, b, b); /*这条语句的输出有两个对的两个错的,符合我的预期*/
return(0);}
输出结果如下图
我的主要问题是,为什么第一个printf的输出没有一个是对的?
本人是小白,希望能有大神帮忙解答,多谢!
首先,
float
在这里会自动转换为double
, 为了方便理解,我们在这里假设sizeof(int)
是 4,sizeof(double)
是 8.然后,针对这一句:
依照
%d\n%f\n%d\n%f
去读,栈里面的数据以及读取的指针将呈现如下形式:所以呢,第一个
%d
读到的实际是 2.5 的前 4 byte。 紧接着第一个%f
读的是 2.5 的后 4 byte, 加上下一个 2.5 的前 4 byte. 同理,第二个%d
读到的是 2.5 的后 4 byte, 而第二个%f
读到的是两个 2.好吧,是不是有点乱。C 语言中是如何定义这种在输出里"类型乱读"的现象呢?
如标准所言,这是 UB (未定义行为),所以至于它为何会输出你截图里的那四个数,可以不必深究。不同编译器的结果也不尽相同。
补充
上面分析了原理,那么也可以顺带分析一下你的第二句为什么可以输出你想要的。
依照
%f\n%d\n%f\n%d
去读,栈里面的数据以及读取的指针将呈现如下形式:运气不错,牛头正好对上了马嘴,你得到了你想要的输出。。。
不要侥幸,老老实实的按类型去
printf
, 才是初学者正确的态度。