将int作为float打印时printf的行为是什么?

我在windows7上使用dev cpp来编译我的代码。

int d = 0x12; char* e = (char*)&d; printf("%d %d\n", sizeof (int), sizeof (float)); printf("%p %p\n", &d, (float*)&d); printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]); printf(" %d | %x | %#1x | %#1x | %#1x |%p\n", d, e[0], e[1], e[2], e[3], &e[0]); getchar(); 4 4 0028FF40 0028FF40 0028FF40 0028FF40 0028FF41 0028FF42 0028FF43 18 | 12 | 0 | 0 | 0 |0028FF40 

你看,如果我使用%d打印d,它打印4个字节的精细。 但是,如果我像下面这样使用%f,它会在必须打印e的第一个字节的位置显示零。 任何人都可以帮助解决为什么会这样 为什么e的内容取决于d的格式?

 int d = 0x12; char* e = (char*)&d; printf("%d %d\n", sizeof (int), sizeof (float)); printf("%p %p\n", &d, (float*)&d); printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]); printf(" %f | %x | %#1x | %#1x | %#1x |%p\n", d, e[0], e[1], e[2], e[3], &e[0]); getchar(); 

输出是:

 4 4 0028FF40 0028FF40 0028FF40 0028FF40 0028FF41 0028FF42 0028FF43 0.000000 | 0 | 0 | 0 | 0x28ff40 |76869F1D 

未定义的行为。

在实践中,您所看到的可能是由于%f使得printf从其参数列表中拉出一个double ,即8字节* 。 但是d大小只有4个字节,所以现在一切都没有对齐。

请记住, printf是一种可变函数,这意味着它是完全非类型安全的; printf必须在没有编译器帮助的情况下从堆栈中提取原始字节。 确保参数与格式字符串精确对应完全取决于您。


*可能。

你被自动类型推广绊倒了。

你好像假设自sizeof(int)== sizeof(float),你可以互换地传递d作为float或int。 但问题是,在C中你无法通过浮动。

在C中,当您在表达式中使用char或short时,它会自动转换为int。 类似地,当您在表达式中使用float时,它会自动转换为double。

因此,当您执行printf(“%f”,d)时,编译器会在进行函数调用之前将int(即四个字节)压入堆栈。 然后在函数中,printf()看到“%f”,并从堆栈中拉出8个字节。 其中四个字节是你的“d”,其他四个是碰巧在那里。 在您的示例中,e [0]和e [1]。

如果要将“d”作为float打印,则需要显式转换它,或者指定给float变量。 在任何一种情况下,编译器都会在调用printf()之前将其转换为double。 (注意:听起来很奇怪,“%f”用于打印双打,而不是浮动。你不能打印浮点数。你可以用“%f”和“%lf”读取浮点数或双打数, scanf(),但在printf()中,“%f”打印双打。)

是的,你从堆栈中拉出8个字节 – 其中4个是0x00000012,其余的是编译器相关的(可能是在构造printf的堆栈帧时被压入堆栈的返回地址)。