楼上说的可能没在点子上,本程序真正出问题的原因应该是:读入a的值的时候由于格式化字符串中的%u
溢出将N的值破坏了,因为N和a均在栈中管理,N的首地址比a的首地址高2个字节,当向a的首地址放入4个字节的数据时,N的低2字节将被覆盖
改成static int N以后,N将不再在栈中管理,因此就不会和栈中的a冲突,因此改为static后就正常了。
下面看一下N和a均在栈中时的汇编代码:
跟踪到scanf("%d",&N);
时:
0x00401566 <+70>: lea 0x58(%esp),%eax
0x0040156a <+74>: mov %eax,0x4(%esp)
0x0040156e <+78>: movl $0x41b000,(%esp)
0x00401575 <+85>: movl $0x1,0x20(%esp)
0x0040157d <+93>: call 0x40b558 <scanf>
可见,N的地址为0x58(%esp)
跟踪到scanf("%u",&a);
时:
0x00401598 <+120>: lea 0x56(%esp),%eax
0x0040159c <+124>: mov %eax,0x4(%esp)
0x004015a0 <+128>: movl $0x41b00b,(%esp)
0x004015a7 <+135>: call 0x40b558 <scanf>
可见,a的地址为0x56(%esp)
在执行本次scanf之前,我先扫一下0x56(%esp)
的地址(此时ESP的值为0x28fe50):
(gdb) x/10bx ($esp+0x56)
0x28fea6: 0x00 0x00 0x0a 0x00 0x00 0x00 0x00 0x00
可见N位于$esp+0x58处,确实是10(0x0000000a)
下面我们给a读入一个127(0x007f),看看0x56(%esp)
的地址变化的情况:
(gdb) x/10bx ($esp+0x56)
0x28fea6: 0x7f 0x00 0x00 0x00 0x00 0x00 0x00 0x00
看到了吗?之前的0x0a
被覆盖掉了,因为%u
使得scanf函数
向&a
处写入了**4**个字节,假如我们输入一个对于unsigned short
会溢出的数,比如4294967295(0xffffffff),你将在屏幕上看到以下输出:
10
请输入a
4294967295
我是a=65535
我是i=1
我是N=65535请输入a
(后面的输出省略)
看吧!N怎么会等于65535(0xffff)!原来就是因为写入的0xffffffff覆盖掉了N的低16位!此时去扫一下内存,一定会发现N所在的0x58(%esp)
变为了0xff 0xff
改成static int N以后,N将不再在栈中管理,因此就不会和栈中的a冲突,因此改为static后就正常了。
个人的一点探讨,如尚未解决您的问题,可追问;若解决了您的问题,请采纳。