我正在研究基于内存地址的问题,发现这很令人困惑(下面的算法主要是计算“ Value”和“ 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);
然后我得到以下输出:
Current V: 00439488
Current E: 004391e0
V-E is: 000002a8
V-E/2L is: 80000154
address is 80000154
Modbuss address:-2147474308
让我感到困惑的是,我的V-E实际上是预期的结果,但是当我将该数字除以2时,结果应该是0x00000154,但是我得到了0x80000154。我正在使用没有任何额外标志的gcc编译器,预期结果应为0x154。
我可以通过掩盖MSB轻松地改进它,但是我只是想知道为什么会发生这种情况。
感谢所有帮助。
您的程序到处都有潜在的和实际的未定义行为,但是核心问题很可能是您未显示的部分代码:E
和V
的类型。我怀疑他们是long
。至少(V-E)/2L
的类型为long
(或更宽),并且将其作为%x
格式说明符的参数传递时,会出现未定义的行为。可能发生的情况是V-E
在第31位上方具有非零位,并且您的系统对printf
(或传递参数的ABI)的实现在打印/读取[ C0]。但是在除以2后,非零位32已下移到位31,并显示在(UB)unsigned int
输出中。