Home > Blockchain >  Why is the change not assigned a new value through the pointer
Why is the change not assigned a new value through the pointer

Time:09-16

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 in b. So it ignores any change attempted through *a and uses 5.1 for b in the printf statement.
  • The compiler stores in the int value 10 in the memory used for b. Later, when it gets b, the bits for the int 10 are reinterpreted as a float. The float type encodes values differently than the int type, so the bits 000…0001010 represent a very small number in the float type. Since the conversion %lf produces only six digits after the decimal point, the small number is display as “0.000000”.
  • Related