通过memcpy将int按位转为float结果为0,求原因解析
I'm trying to create a float by directly setting its binary bits, and I learned memcpy is a good approach for this. I wrote the following code:
#include <stdio.h> #include <string.h> float i2f(int i) { float result; memcpy(&result, &i, sizeof(int)); return result; } int main() { printf("Size of int is %d.\n", sizeof(int)); printf("Size of float is %d.\n", sizeof(float)); int i = 0x7fffff; float f = i2f(i); printf("int value is %d.\n", i); printf("float value is %f.\n", f); return 0; }
When I run it, the output is:
Size of int is 4. Size of float is 4. int value is 8388607. float value is 0.000000.
Why am I getting 0.0 for the float value?
Let's break this down step by step to understand what's happening:
1. First, recall 32-bit IEEE 754 float structure
A single-precision float uses 32 bits split into three parts:
- 1 sign bit (0 = positive, 1 = negative)
- 8 exponent bits (with a fixed bias of 127)
- 23 mantissa (fraction) bits (with an implicit leading
1for normal numbers)
2. Analyze the bit pattern of your int
Your int 0x7fffff is equal to 8388607, which in binary is 23 consecutive 1s. When stored as a 32-bit int, the full bit pattern is:00000000 11111111 11111111 11111111
When you memcpy this into a float, we're interpreting this exact bit pattern as an IEEE 754 float.
3. Interpret the bit pattern as a float
Breaking down the bits for the float:
- Sign bit:
0(positive value) - Exponent bits: The first 8 bits after the sign are
00000000 - Mantissa bits: The remaining 23 bits are all
1s
In IEEE 754, an exponent of all 0s means this is a denormalized (subnormal) number. For denormals:
- We use an implicit leading
0instead of the usual1 - The effective exponent is
1 - 127 = -126(instead ofexponent_value - 127)
Calculating the actual value:
value = (-1)^sign * (0.mantissa) * 2^(effective_exponent) value = 1 * (0.111...111) * 2^-126
This equals approximately 1.175494e-38—an extremely small number.
4. Why %f shows 0.000000
The %f format specifier by default displays 6 decimal places. Since 1.175494e-38 is way smaller than 0.000001 (the smallest non-zero value that shows up with 6 decimal places), it gets rounded to 0.000000 when printed with %f.
5. Verify the actual value
If you use a format specifier that handles very small numbers, like %e (scientific notation) or %g, you'll see the real value. Try changing your printf line to:
printf("float value is %e.\n", f);
You'll get output like 1.175494e-38, which confirms the float isn't actually zero—it's just too small to show up with the default %f formatting.
内容的提问来源于stack exchange,提问作者zzz_zzz

