C划分时,MSB得到设置

问题描述 投票:1回答:1

我正在研究基于内存地址的问题,发现这很令人困惑(下面的算法主要是计算“ 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轻松地改进它,但是我只是想知道为什么会发生这种情况。

感谢所有帮助。

c division
1个回答
0
投票

您的程序到处都有潜在的和实际的未定义行为,但是核心问题很可能是您未显示的部分代码:EV的类型。我怀疑他们是long。至少(V-E)/2L的类型为long(或更宽),并且将其作为%x格式说明符的参数传递时,会出现未定义的行为。可能发生的情况是V-E在第31位上方具有非零位,并且您的系统对printf(或传递参数的ABI)的实现在打印/读取[ C0]。但是在除以2后,非零位32已下移到位31,并显示在(UB)unsigned int输出中。

© www.soinside.com 2019 - 2024. All rights reserved.