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

时间:2011-11-20 18:44:26

标签: c casting floating-point int 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

3 个答案:

答案 0 :(得分:8)

未定义的行为。

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

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

<小时/> *可能。

答案 1 :(得分:2)

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

你好像假设自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”打印双打。)

答案 2 :(得分:1)

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