-5

I put the code directly.

#include <stdio.h>
struct A
{
    int a;
    int b;
};
int main()
{
    struct A test;
    double *p = (double *)&(test.a);
    *p = 5;

    printf("variable a: %d\n", &test.a);
    printf("variable b: %d\n", &test.b);
    return 0;
}

I run this code in centos7, the compiler is gcc4.8.5.And my computer uses little ending to store.

As you see, the memory of variable b will be overwritten, I expected a is 0x0000 0005 and b is 0x0000 0000.

But the answer is:

variable a: 0
variable b: 1075052544

Why variable a is 0x 0000 0000 and b is 0x4014 0000?

UKeeySDis
  • 51
  • 8
  • 5
    This is undefined behavior. Also, the `double` 5 corresponds to the 64-bit integer `0x4014000000000000` so you can probably figure out what's happening. Hint: `double` can be larger than `int`. – unwind Oct 11 '17 at 12:52
  • 3
    You get unexpected result because you lied to your compiler, and it figured a way to get back at you. You told the compiler that `&(test.a)` is an address of a `double`, but it is an address of an integer. – Sergey Kalinichenko Oct 11 '17 at 12:54
  • You can twiddle with the optimization settings and get your compiler to compile code where the result is something *else* as well. – Antti Haapala -- Слава Україні Oct 11 '17 at 12:56
  • @Bathsheba just writing here that the output doesn't match the code, so, why did you reverse my downvote?! – Antti Haapala -- Слава Україні Oct 11 '17 at 12:58
  • @AnttiHaapala: Oops. Did not see that. I've withdrawn my upvote. Luckily the answer stays the same. – Bathsheba Oct 11 '17 at 12:59
  • Your code's got an error... you meant to output `test.a`, but copied wrong code here, which outputs `&test.a`. Both are ill-defined examples. – Antti Haapala -- Слава Україні Oct 11 '17 at 13:01
  • I know that should not use the double pointer to the int variable, I just want to test the memory coverage. – UKeeySDis Oct 11 '17 at 13:08
  • @unwind Thanks, you are right.The `double 5` corresponds to the 64-bit integer `0x40140000 00000000`.So I get variable `b` is `0x 40140000`, verify that my idea is correct, the value of the variable `b` is indeed covered. But I just don't konw why `double 5` corresponds to the 64-bit integer `0x40140000 00000000`?How it is stored? – UKeeySDis Oct 11 '17 at 13:24
  • @dasblinkenlight This is a test, I just want to verify that the other half of the 4 bytes does become the value of the variable `b`. – UKeeySDis Oct 11 '17 at 13:26
  • @UKeeySDis That's the thing, though - you can't rely on the results of a test if there is undefined behavior. – Sergey Kalinichenko Oct 11 '17 at 13:29
  • @AnttiHaapala In fact this is a fixed value, because the value of the variable b is a double pointer to a value after the remaining 4 bytes. – UKeeySDis Oct 11 '17 at 13:30
  • @UKeeySDis Read some basic material on computer floating-point, such as [Wikipedia's entry on IEEE-754](https://en.wikipedia.org/wiki/IEEE_754). – unwind Oct 11 '17 at 14:59
  • 1
    The code is a strict aliasing violation and therefore completely undefined behavior. It is pointless to reason about the effects of undefined behavior. – Lundin Oct 11 '17 at 15:18

2 Answers2

4

The behaviour of your code is undefined.

You can't dereference p once you've set it to the address of something that is not a double type.

To see what your compiler has done with this input, check the generated assembly.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • In my computer, `int` occupies 4 bytes, `double` occupies 8 bytes, I use double pointer to int and assignment, it should override the value of variable b, so I think b should be 5, a should be 0.And `1075052544` is a fixed value that does not change with each run or change optimization. – UKeeySDis Oct 11 '17 at 13:07
  • 1
    You can think what you want to think. That's obviously not what is happening. The fact remains the behaviour is undefined. – Bathsheba Oct 11 '17 at 13:08
  • The double 5 corresponds to the 64-bit integer `0x4014000000000000`.So I get `b` is `0x4014 0000`, the value of the variable b is the other half of the 4 bytes. – UKeeySDis Oct 11 '17 at 13:28
  • 1
    @UKeeySDis: you could verify that by setting a 64 bit integer to a given value, a double to another value, and calling `memcmp`. All perfectly defined behaviour. – Bathsheba Oct 11 '17 at 13:32
  • This is really a good idea, I verify it.But why the double 5 corresponds to the 64-bit integer `0x4014000000000000`?How it is stored?Thank you very much. – UKeeySDis Oct 11 '17 at 13:41
  • @UKeeySDis As soon as you invoke undefined behavior, you can no longer reason about your program. The compiler may optimize the machine code in completely crazy ways and the program may run amok. You cannot predict anything and you cannot expect anything. Which is why undefined behavior is always a severe bug. Read up about "the strict aliasing rule". – Lundin Oct 11 '17 at 15:20
1

The behaviour of your code is undefined.

Clang compiler generate warning message:

source_file.c:13:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("%d\n", &test.a);
            ~~     ^~~~~~~
source_file.c:14:20: warning: format specifies type 'int' but the argument has type 'int *' [-Wformat]
    printf("%d\n", &test.b);
            ~~     ^~~~~~~
msc
  • 33,420
  • 29
  • 119
  • 214