C程序关于整型数据溢出的几种情况求解
在谭的书上有讲#include <stdio.h>
void main()
{
int a,b;
a=32767;
b=a+1;
printf(“%d,%d”,a,b);
}
这个将b改为long就可得到希望的结果
但我采用
#include <stdio.h>
void main()
{
int a;
long b;
a=32767;
b=a+1;
printf(“%d,%ld”,a,b);
}
所得到的仍然是32767,-32768
如果采用
#include <stdio.h>
void main()
{
int a;
long b;
a=32767;
b=a+1;
printf(“%d,%d”,a,b);
}
结果和上面的一样
采用
#include <stdio.h>
void main()
{
int a,b;
a=32767;
b=a+1;
printf(“%d,%ld”,a,b);
}
结果是a为32767,b的值却是一个很大很奇怪的数
采用
#include <stdio.h>
void main()
{
long int a,b;
a=32767;
b=a+1;
printf(“%d,%d”,a,b);
}
结果也很奇怪 a为32767,b却变成了0
困惑了半天也没想通 所以发到帖吧来寻求明白的人给我点提示 感激不尽!
PS:
我的环境是TC2.0
我用
#include <stdio.h>
void main()
{
int a,b;
a=32767;
b=a+1;
printf("%d,%d\n",a,b);
} 已经得得正确结果 我主要是想了解出现前面几种情况的原因
先在这里谢谢了!
----------------解决方案--------------------------------------------------------
long -> %ld 当 数据益处的时候 是随即的值 回答完毕
----------------解决方案--------------------------------------------------------
我测试的结果如下:
1.32767,32768请按任意键继续. . .
2.32767,32768请按任意键继续. . .
3.32767,32768请按任意键继续. . .
4.32767,32768请按任意键继续. . .
我用GCC编译器。
至于为什么是这结果。因为GCC是32位编译器,%d对应32位整型。我想无论如何都不会溢出的吧……上次为了有溢出的效果,还得手动加上%hd………………
至于LZ的问题。你分两方面考虑:1 变量内部的实际值是多少?
比如short a;long b;a为32767时其实际值为0x7FFF,b为a+1的实际值是0x00008000。显然b没有发生溢出,其值为32768。当short a,b;a=0x7FFF,b会等于0x8000而最高位表示正数的0被溢出为1,所以b现在是负数。数值大家可以算出来,是-0x08000,即-2^15=-32768。
2 显示的的时候,实际输出的是多少?
首先强调一点。就是printf并不知道你后面的数字是什么类型。它只是按照你给出的格式控制符,自己往后面取相应的位数,当作相应的类型而已。举个最简单的例子:
printf("%hx,%hx",0x12345678,0);
输出多少?有人说是5678,0,错误。首先h规定了只取16位。而后面0x12345678有32位。于是只取前16位,根据Little-Endian,前16位为9x5678,然后取后16位,后16位为0x1234。如果你是TC,可以写成0x12345678L比较安全一点,反正应该是5678,1234这个结果。
回到原题。对于上面第一种情况(short a;long b;)a倒是%hd这个毫无疑问了,对于b,问题就来了。你用%hd是100%会得到-32768,因为它只取了b的低16位然后当作一个short!所以b高位是什么,就没什么必要了(这里没用到高位),而如果是第二种情况,也是同样的结果。
如果b用%ld,对于第一个,很正常地读到了32位值,然后忠实地显示为32768。对于第二个,为什么会乱码呢?因为b根本只有16位,它读了b的16位以后又跟过去读了b后面的16位,这16位是随机的数据(在本题里,是上一个函数,即main函数的返回地址,也就是Startup Code的地址),那么当然会是一个很怪异的大数字咯。
不知道你看懂没,没看懂的话,跟帖问。关键是搞清楚这两个不同的过程。
----------------解决方案--------------------------------------------------------
补充:上面的代码printf("%hx,%hx",0x12345678,0);,TC上运行的确是5678,1234,符合预期,但是GCC和VC居然都是5678,0。晕了……怎么回事?我记得如果是va_arg的话,的确只是按照位来取,而没有办法判断变量的间隔的啊??不明白了,于是使用了下面的代码:
printf("%hx,%hx",0x12345678abcdLL,0);
得到了预期值abcd,1234。NND,好狡猾,无论是什么类型的变量居然都占用32位空间,差点被忽悠了……
----------------解决方案--------------------------------------------------------
恩 基本看懂了
我之前也用了gcc 当时就发现没有溢出 感觉gcc和TC至少默认的int所占用的存储空间不同 gcc要大些
真的很感谢你
----------------解决方案--------------------------------------------------------