1

我不明白为什么以下相同的操作会报告两个不同的输出。当我的 num 被声明为负值并将 num 添加到 baseAddr 时,我看到我的 addr 超出了 32 位范围。另一方面,如果我将 num 声明为正值并进行减法,我确实看到了正确的结果。即我的结果输出被准确报告。有人可以解释一下下面的计算有什么问题吗?

/* Architecture is powerpc. Program cross-compiled for powerpc. Gcc Version- 4.6.2 */
#include <stdio.h>
typedef unsigned long long u_int64;
typedef unsigned long u_int32;

int main() {
   u_int64 baseAddr = 0x8e008128;
   u_int32 num = -360;
   u_int64 addr = baseAddr + num;
   printf("\nAddr 1st step = 0x%llx\n", addr);

   /* Same operation, but slightly different */
   num = 360;
   addr = baseAddr - num;
   printf("\nAddr 2nd step = 0x%llx\n", addr);
   return 0;
}

/* Output:
Addr printed is 0x18e007fc0, but I need just 0x8e007fc0
/diagsk10copy/bin # ./e500GPR

Addr 1st step = 0x18e007fc0 //Wrong
Addr 2nd step = 0x8e007fc0
*/
4

2 回答 2

4

u_int32是无符号类型;将 -360 分配给它会导致整数溢出并导致num持有一个非常大的正值。

于 2012-09-26T20:17:54.640 回答
3

u_int32未签名。您分配给它的负数360将被重新解释为正数 32 位数字。当您将它添加到 时u_int64,该值将扩展为 32 个零以匹配另一个操作数的大小。这不是您想要的:由于该数字是负数,因此您需要上半部分的所有数字,以便在加法结果以比最大值大 1 的数字为模减少后,加法产生所需的效果可以用u_int64*表示。

如果您声明numas u_int64,则第一部分和第二部分会产生预期的数字(ideone 上的演示)。

u_int64 baseAddr = 0x8e008128;
u_int64 num = -360;
u_int64 addr = baseAddr + num; // Works!
printf("\nAddr 1st step = 0x%llx\n", addr);


* 6.2.5 (9) “涉及无符号操作数的计算永远不会溢出,因为不能由结果无符号整数类型表示的结果会以比结果可以表示的最大值大一的数字为模减少类型。”。感谢Daniel Fischer找到标准的相关部分!

于 2012-09-26T20:30:11.503 回答