我对以下代码的输出感到困惑:
float a = 1.32;
int* b;
b= &a;
printf("%d", *b);
这段代码将float转换为int,但我得到的输出是:1068037571
这是否与计算机的IEEE 754转换功能有关? 谢谢!
答案 0 :(得分:10)
您的程序调用未定义的行为。您只需将float
的表示重新解释为int
。您绝对不会将int
转换为float
。你不能指望任何特定的行为。
要将float转换为int,您可以使用如下代码:
int b = a;
将float
截断为int
。
答案 1 :(得分:5)
您在使用代码时正在查看浮点数的存储方式。浮点在内存中占用4个字节(通常),如下所示(维基百科中的示例):
运行代码时,假装这些位是四字节整数:
float a = 1.32;
int* b;
b= &a;
printf("%d", *b);
如果要查看十六进制表示,只需执行
printf("%08x", *b);
你会得到
3f9d70a4
意味着位模式是
00111111100111010111000010100100
打破它:
0 01111111 00111010111000010100100
签署位0
指数01111111
分数(1)00111010111000010100100
你会发现二进制数
100111010111000010100100 = 10317988
那个
10317988.0 / (4096.0*2048.0) = 1.23
更新完整程序,准确显示如何执行此操作:
#include <stdio.h>
#include <math.h>
#include <stdint.h>
int main(void) {
float a = 1.23;
uint32_t *b = (uint32_t *)&a;
uint32_t signbit;
uint32_t exponent;
uint32_t mantissa;
uint32_t fpAsInt;
fpAsInt = *b;
signbit = (fpAsInt & 0x80000000) >> 31;
exponent = (fpAsInt & 0x7F800000) >> 23 ;
mantissa = (fpAsInt & 0x007FFFFF) | 0x00800000;
printf("fpAsInt: 0x%08x\n", fpAsInt);
printf("sign bit: %d\n", signbit);
printf("exponent: 0x%02x\n", exponent);
printf("mantissa: 0x%03x\n", mantissa);
printf("the value is %10f\n", ((signbit == 1)?-1.0:1.0)*mantissa / pow(2.0, (127 - exponent + 23)));
printf("the original value was %10f\n", a);
}
打印结果
fpAsInt: 0x3f9d70a4
sign bit: 0
exponent: 0x7f
mantissa: 0x9d70a4
the value is 1.2300000191
the original value is 1.2300000191
我在最后一行使用浮点数学似乎是作弊 - 有效的批评,但这里的重点是展示如何构造浮点,而不是如何使用整数数学来提取值。
注 - 我假设浮点数是IEEE 4字节表示。此外,我包括一些特定的转换来摆脱编译器警告。只有当你确定你知道自己在做什么时才这样做......
ONE MORE EDIT
有人指出代码仍然存在未定义的行为。为了解决这个问题,并且仍然让您对上述内容有所了解,让我们再来一次。现在我使用一个位数组和一个浮点数的联合来“合法地”访问不同的元素 - 并且在使用-Wall -pedantic
进行编译时没有得到任何警告。这可能还不够,但这是我所知道的最好的......
#include <stdio.h>
#include <math.h>
#include <stdint.h>
union ieee754_float
{
float f;
/* This is the IEEE 754 single-precision format on a little-endian machine. */
struct
{
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
} ieee;
};
int main(void) {
float a = 1.23;
union ieee754_float *pa;
pa = (union ieee754_float*)&a;
uint32_t signbit;
uint32_t exponent;
uint32_t mantissa;
signbit = pa->ieee.negative;
exponent = pa->ieee.exponent;
mantissa = pa->ieee.mantissa | 0x00800000;
printf("sign bit: %d\n", signbit);
printf("exponent: 0x%02x\n", exponent);
printf("mantissa: 0x%03x\n", mantissa);
printf("the value is %.10f\n", ((signbit == 1)?-1.0:1.0)*mantissa / pow(2.0, (127 - exponent + 23)));
printf("the original value is %.10f\n", a);
}
答案 2 :(得分:2)
回到这些基本规则可以回答StackOverflow上C
标签中的许多问题:
&
获取变量并生成指针*
获取指针并生成变量所以你说“接受这个浮点变量并让我成为一个指针。现在接受那个指针,让我成为一个int变量。”你从来没有说过“取这个漂浮值并让我成为一个int值”。你说“把一个可以变成浮点变量的指针转而变成一个int变量”。当你这样做时会发生什么?这完全取决于编译器的决定。