#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。对此有任何见解
答案 0 :(得分:2)
致@ Cornstalks&#39;要点:INT_MIN
为0x80000000
,而(int)-1
为0xFFFFFFFF
为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。
因此,如果你的常数大于int
(unsigned int
范围内的最大值),则常数(如果为正)的类型为%d
,但指令signed int
期望值UMAX_INT
。因此,它将显示一些负数。
最糟糕的是,如果您的常量值大于unsigned int
(long 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>
fun1
和fun2
应打印“预期的”积极结果。