I'm working on a memory address based problem and I found this is very confusing (Below algorithm is mainly calculate the address difference between "Value" and "nv_var.EEStart"):
ValueI = (int*)(Value); // ValueI is int*
EP = (int)(&nv_var.EEStart); // EP is int
E = (long)(EP); // E is long
V = (long)(ValueI); // V is long
adr = (V - E) / 2L; // adr is long
printf("Current V: %.8x\n", V);
printf("Current E: %.8x\n", E);
printf("V-E is: %.8x\n", (V - E));
printf("V-E/2L is: %.8x\n", (V - E) / 2L);
printf("address is %.8x\n", adr);
Then I got the following output:
Current V: 00439488
Current E: 004391e0
V-E is: 000002a8
V-E/2L is: 80000154
address is 80000154
Modbuss address:-2147474308
What confused me is my V-E is actually the expected result, but when I divide this number by 2, the result should be 0x00000154, but I got 0x80000154. I'm using gcc compiler without any extra flag, and the expected result should be 0x154.
I can improve it easily by masking off the MSB, but I just wondering why this will happen.
Thanks for all the help.
Your program has potential and actual undefined behavior all over the place, but the core problem is likely in part of the code you're not showing: the types of E
and V
. I suspect they're long
. At least (V-E)/2L
has type long
(or wider), and when you pass that as the argument for a %x
format specifier, you get undefined behavior. What's likely happening is that V-E
has nonzero bits above bit 31, and your system's implementation of printf
(or argument-passing ABI) masks off all the bits outside the size of unsigned int
when printing/reading an argument for %x
. But after dividing by 2, a nonzero bit 32 has been shifted down to bit 31 and shows in the (UB) printf
output.
User contributions licensed under CC BY-SA 3.0