在C中将int打印为float
我为Little Endian使用Visual Studio TC编译器。 以下是这段代码:
void main()
{
float c = 1.0;
int a = 0x3F800000;
int *ptr = (int *)&c;
printf("n0x%Xn", *ptr);
printf("na = %f", a);
printf("nc = %f", c);
return;
}
输出是:
0x3F800000
a = 0.000000
c = 1.000000
浮点值1.0是0x3F800000,并且在Little Endian的存储器中存储为00 00 80 3F。 相同的值被分配给int a。 如何printf打印0.000000为int而1.000000为float c? 我已经看到它在printf中使用%f打印时将所有整数值打印为0.000000。
另外,由于printf是可变参数函数,它如何知道寄存器中传递的值是int还是float?
我的心理能力告诉我Adam Liss的评论是正确的答案: float
参数被提升为double
,所以printf()
函数期望这种情况发生:它期望在堆栈上有一个64位的值,但是会得到32位加上垃圾数据碰巧为零。
如果增加显示精度,则显示应该是a = 0.00000000001
。
这也意味着这应该工作:
void main()
{
double c = 1.0;
long long a = 0x3FF0000000000000;
long long *ptr = (long long *)&c;
printf("n0x%llXn", *ptr);
printf("na = %f", a);
printf("nc = %f", c);
return;
}
我用gcc编译了你的代码,生成的代码如下:
movl $0x3f800000, %eax
movl %eax, -4(%ebp)
movl $1065353216, -8(%ebp)
leal -4(%ebp), %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
movl (%eax), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl -8(%ebp), %eax
movl %eax, 4(%esp)
movl $LC2, (%esp)
call _printf
flds -4(%ebp)
fstpl 4(%esp)
movl $LC3, (%esp)
call _printf
这可能会给你一个提示,即float参数不是从常规堆栈中取出,而是从浮点堆栈中取出......我认为会有一些随机而非0的内容。
As -Wall
指出: warning: format '%f' expects type 'double', but argument 2 has type 'int'
。 这是未定义的行为,这也在这里更详细地解释。
如果转换规范无效,则行为未定义。 如果任何参数不是相应覆盖规范的正确类型,则行为是未定义的。
所以你在这里看到的是编译器构建者决定发生的事情,可以是任何事情。
链接地址: http://www.djcxy.com/p/90299.html