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*aand uses 5.1 forbin theprintfstatement. - The compiler stores in the
intvalue10in the memory used forb. Later, when it getsb, the bits for theint10are reinterpreted as afloat. Thefloattype encodes values differently than theinttype, so the bits 000…0001010 represent a very small number in thefloattype. Since the conversion%lfproduces only six digits after the decimal point, the small number is display as “0.000000”.
