#include <stdio.h>
int main () {
float a = 123.0;
unsigned char ch, *cp;
ch = 0xff;
cp = (unsigned char *) &a;
printf ("%02x", ch&(*(cp+3)));
printf ("%02x", ch&(*(cp+2)));
printf ("%02x", ch&(*(cp+1)));
printf ("%02x\n", ch&(*(cp+0)));
/*I have written this program to see binary representation, but I can not understand the output, the binary representation?
}
See Wikipedia: http://en.wikipedia.org/wiki/Single_precision_floating-point_format, which describes single precision floating point (a typical C float
, but depends on the compiler) as a 1-bit sign, 8-bit biased exponent, and 24-bit mantissa (23-bits stored).
For your example:
123.0 = 42f60000hex = 0 10000101 11101100000000000000000bin
1-bit sign = 0 (indicating positive number)
8-bit biased exponent = 10000101bin = 133dec - 127dec = 6dec
23-bit mantissa = 11101100000000000000000bin = 1.111011bin (note implied leading 1)Converting 1.111011bin x 26dec = 1111011.0bin = 123.0dec
Guessing about your question how is double number (e.g. 123.45) stored in a float variable or double variable or long double variable?
: If you store a double-value (like the literal "123.0") into a float variable, the compiler will static_cast<float>
the value so it becomes a valid float value.
So, apart from possible compiler warnings, the following
int main () {
float foo = 123.0;
}
is basically the same as
int main () {
float foo = static_cast<float>(123.0);
}
If you want to explicitly state a float-literal, use the f
or F
postfix:
int main () {
float foo = 123.0f; // alternatively: 123.f, 123.F
}
Just looked up the grammar for floating-literals, for the curious:
floating-literal:
fractional-constant exponent-part_opt floating-suffix_opt
digit-sequence exponent-part floating-suffix_opt
fractional-constant:
digit-sequence_opt . digit-sequence
digit-sequence .
exponent-part:
e sign_opt digit-sequence
E sign_opt digit-sequence
Here some examples for floating-point literals that require no conversion (but possibly rounding):
float a = 1.f,
b = 1.0f,
c = .0f,
d = 1e1f,
e = 1.e1f,
f = 1e-1f,
g = 1e+1f,
h = 1E+1F;
If conversion is needed, e.g.
float a = 1., // double
b = 1.L,// long double
c = 1; // integer
The following applies:
4.8 Floating point conversions [conv.double]
An rvalue of floating point type can be converted to an rvalue of another floating point type. If the source value can be exactly represented in the destination type, the result of the conversion is that exact representation. If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values. Otherwise, the behavior is undefined.
4.9 Floating-integral conversions_ [conv.fpint]:
An rvalue of an integer type or of an enumeration type can be converted to an rvalue of a floating point type. The result is exact if possible. An rvalue of an integer type or of an enumeration type can be converted to an rvalue of a floating point type. The result is exact if possible. Otherwise, it is an implementation-defined choice of either the next lower or higher representable value.
So in summary, if you put a literal of type double
or long double
(or some integer) into a float
, the compiler will implicitly convert that value, if it can be converted exactly. Otherwise, it is platform-dependent how the result is stored; in case the value exceeds the representable range, you enter the world of undefined behaviour *.
* The Dreaded Realm of Undefined Behaviour, where an evil compiler writer may find it funny to beep out an infernal sound through your loudspeakers and make you bleed through the ears, and still be sanctioned by the standard (not necessarily by local laws, though).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With