Why isn't variable b assigned the value 10?
int *a;
int c = 5;
float b = 5.1;
a = (int*)&b;
*a = 10;
printf ("a = %p, &b = %p, b = %lf, *a = %d\n", a, &b, b, *a);
result: b = 0.00000, *a = 10
CodePudding user response:
While we may assign a plain int
to a float
and vice versa, and then get an implicit conversion, this does not apply to pointers.
a = (int*)&b
is an invalid pointer conversion. You lie to the compiler and say that the thing stored at address &b
is an int
. Which is it not. This is undefined behavior - the two different types could have different sizes - but it's also a "strict aliasing violation" What is the strict aliasing rule?
Since your code contains undefined behavior, anything can happen. What is undefined behavior and how does it work? One of many possible behaviours is that the system tries to re-interpret the binary representation as a float number where the 0xA ends up so far down in the fraction part that it gets rounded to zero. The program may as well crash or display any random garbage.
CodePudding user response:
In *a = 10;
, the memory of b
, which was declared to be a float
, is accessed using *a
, for which the type is int
. This violates the rule in C 2018 6.5 7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object, …
It goes on to list some other allowed cases, but changing a float
object through an int
type is not among them. Because this rule is violated, the C standard does not define the behavior of the program. (C 2018 4 2: “If a "shall" or "shall not" requirement that appears outside of a constraint or runtime-constraint is violated, the behavior is undefined.”)
Although the C standard does not define the behavior, two results are common in current compilers:
- The compiler knows the value 5.1 (approximately, after conversion to
float
) was stored inb
. So it ignores any change attempted through*a
and uses 5.1 forb
in theprintf
statement. - The compiler stores in the
int
value10
in the memory used forb
. Later, when it getsb
, the bits for theint
10
are reinterpreted as afloat
. Thefloat
type encodes values differently than theint
type, so the bits 000…0001010 represent a very small number in thefloat
type. Since the conversion%lf
produces only six digits after the decimal point, the small number is display as “0.000000”.