跃2.0 2017-11-10 12:31 采纳率: 40%
浏览 1032
已采纳

为什么这个变量不能控制循环,变量作用域

#include
int main()
{
int N;
int i = 0;
scanf("%d",&N);
while(i<N)
{
unsigned short a,g,d;
printf("请输入a\n");
scanf("%u",&a);
printf("我是a=%u\n",a);
i++;
printf("我是i=%d\n",i);
printf("我是N=%d",N);
}

return 0;

}//如题,N不能控制循环,我怀疑是因为变量作用域问题,可是为什么呢,我把N改成static int N,把i改成static int i就又可以了,有没有办法可以不改,求解答,

  • 写回答

7条回答

  • 造轮使者 2017-11-10 15:07
    关注

    楼上说的可能没在点子上,本程序真正出问题的原因应该是:读入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后就正常了。

    个人的一点探讨,如尚未解决您的问题,可追问;若解决了您的问题,请采纳。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型