我无法理解为什么以下相同的操作会报告两种不同的输出。当我的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
*/
答案 0 :(得分:4)
u_int32
是无符号类型;为它分配-360将导致整数溢出并导致num
保持非常大的正值。
答案 1 :(得分:3)
u_int32
未签名。您分配给它的负360
被重新解释为正32位数。当您将其添加到u_int64
时,值会以32个零进行扩展,以匹配另一个操作数的大小。这不是你想要的:由于数字为负数,你需要在上半部分中的所有数字,以便在加法结果减去模数大于最大值的数量后,加法产生所需效果可以用u_int64
* 表示。
如果您将num
声明为u_int64
,则第一部分和第二部分会产生预期的数字(demo on 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)&#34;涉及无符号操作数的计算永远不会溢出,因为无法用结果无符号整数类型表示的结果以模数大于1的数量减少结果类型可以表示的最大值。&#34;。谢谢Daniel Fischer找到标准的相关部分!