C陷阱与缺陷中有关scanf的一道题


最近重读了一下《C陷阱与缺陷》,发现一道题挺有意思的,这道题是一段简单的代码,如下所示:

#include <stdio.h>
int main(){
    int i;
    char c;
    for(i = 0;i < 5;i++){
        scanf("%d",&c);
        printf("%d",i);
    }
    printf("\n");
    return 0;
}

注意scanf(“%d”,&c),在读入时分两种情况:
(1)读入时是数字,此时程序会陷入死循环,读入一个数字就输出一个0,造成这种情况的原因是在字符c的地址上,程序以“%d”存储了一个整型数据,而字符c本来是一个字节,假设int占四个字节(我的机器上这样的),那么字符c的地址附近的内存会被覆盖。下面以图形化的形式说明这种情况

(gdb调试程序)

若当前时刻i = 1,打印i的地址是0xbffff3fc,c的地址是0xbffff3fb,未执行scanf时的内存内容如下

内容(从内存地址开始的四个字节内容)内存地址
0x01 0x00 0x00 0x000xbffff3fc
0x01 0x01 0x00 0x000xbffff3fb

执行了scanf以后(假设读入了数字5),内存的情况如下图所以

内容(从内存地址开始的四个字节内容)内存地址
0x00 0x00 0x00 0x000xbffff3fc
0x05 0x00 0x00 0x000xbffff3fb

显然,在执行完scanf后,从地址0xbffff3fb开始的四个字节被0x05 0x00 0x00 0x00 覆盖了,变量i的低端部分被置0,而i的高端部分本身就是0,那么此时i的值就变成了0,i的值始终都在0和1之间,就形成了最后的死循环。

(2)读入的是非数字的字符,那么scanf就会遇到读入数据与scanf期待的%d类型不符,导致stdin流出现堵塞,下次循环将不再读入数据除非清空stdin缓冲区,最终导致的结果就是直接输出01234

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值