添加超出0xFFFFFFFF的有符号整数

时间:2013-09-11 02:18:02

标签: c

#include <stdio.h>

void fun3(int a, int b, int c)
{
   printf("%d \n", a+b+c );
}
void fun2 ( int x, int y)
{
   fun3(0x33333333,0x30303030, 0x31313131);
   printf("%d \n", x+y);
}
fun1 (int x)
{
   fun2(0x22222222,0x20202020);
   printf("%d  \n", x);
}
main()
{
  fun1(0x1111111);
}

我正在通过上面的程序来了解堆栈损坏。我得到上述程序的o / p有一些不需要的值。我能理解的是,如果增加的值超过0xFFFFFFFF,则小的负整数变为最大值,表示-1变为0xFFFFFFFF。对此有任何见解

3 个答案:

答案 0 :(得分:2)

致@ Cornstalks&#39;要点:INT_MIN0x80000000,而(int)-10xFFFFFFFF为2的补码(无论如何,在32位系统上)。

这允许指令集在签名算术中执行以下操作:

1 + -2 = -1

变为(为了简洁而签名short

0x0001 + 0xFFFE = 0xFFFF

......然后:

1 + -1 = 0

在内部用溢出表示为

0x0001 + 0xFFFF = 0x0000

还来到@ Cornstalks&#39; point:内部表示(以及溢出添加)是一个实现细节。 C实现(和指令集)不需要表示2的补码中的整数,因此为有符号整数类型提供十六进制值可能会将您绑定到C实现的子集。

答案 1 :(得分:2)

编辑(更正)(我错过了这一点。我的答案适用于常数,但问题包含函数的参数,那么这里发生的是有符号整数对象的溢出,并且正确指出在@Cornstalks的评论中,这是未定义的行为)。 的 /修改

fun1() printf()以错误的方式使用"%d" 您写了int来接受MAX_INT,但如果您的数字大于MAX_INT,则情况并非如此。

您必须检查系统中MAX_INT的值 如果以十六进制格式编写整数常量,则标准C(ISO C99或C11)会尝试按照以下顺序将值放在常量可以适合的第一种类型中:

  

int,unsigned int,long int,unsigned long int,long long int,   unsigned long long int。

因此,如果你的常数大于intunsigned int范围内的最大值),则常数(如果为正)的类型为%d,但指令signed int期望值UMAX_INT。因此,它将显示一些负数。

最糟糕的是,如果您的常量值大于unsigned intlong int, unsigned long int, long long int范围内的最大值),那么常量的类型将是unsigned int的第一个,精度严格大于%d 这意味着 printf("%lld", (long long int) 0x33333333333); 成为错误的指令。

如果你不能完全确定你的值有多大,你可以对最大整数类型进行强制转换:

%lld

指令long long int代表%llu 如果您对正值感兴趣,则必须使用unsigned long long int并转换为 printf("%llu", (unsigned long long int) 0x33333333333);

INT_MAX

通过这种方式,你可以避免任何“有趣”的数字,就像你显示大数字而不失去任何精确度一样。

备注:常量UINT_MAX,{{1}}等位于limits.h

重要事项:强制转换的自动序列仅对八进制和十六进制常量有效。对于十进制常量,还有另一条规则:

  

int,long int,long long int。

答案 2 :(得分:1)

fun3将尝试打印值0x94949494。这大于0x7FFFFFFF的最大4字节整数值,因此它将“溢出”并且(几乎在今天制造的每台计算机上)产生(如果我的算法正确)产生负数-0x6B6B6B6C,即-1802201964。 / p>

fun1fun2应打印“预期的”积极结果。