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
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)
User contributions licensed under CC BY-SA 3.0