在《C陷阱与缺陷》连接(第四章)那一章中,有这样一个程序:

  1. #include <stdio.h>
  2. main()
  3. {
  4. int i;
  5. char c;
  6. for(i = 0; i < 5; ++i)
  7. {
  8. scanf("%d", &c);
  9. printf("%d ", i);
  10. }
  11. printf("\n");
  12. }

这是一个关于printf()与scanf()在不同情形下可以接受不同类型的参数的一个例子。

如果我们输入0 1 2 3 4, 并不一定能够得到0 1 2 3 4。在有些编译器上,可能得到0 0 0 0 0 1 2 3 4。
为什么呢?原因就像书上所说的一样,问题的关键在于c被声明为char类型,而不是int类型。当程序要求scanf()读入一个整数,应该给它传递一个指向整数的指针。而程序中scanf()得到的却是一个指向字符的指针,scanf()并不能分辨这种情况。它只是将这个指向字符的指针作为指向整数的指针而接受,并在指针指向的位置存储一个整数。因为整数所占的存储空间要大于字符所占的存储空间,所以字符c附近的内存将被覆盖。
下面,我将详细说明一下上面所说的这一种情况,注意,只有某些编译器会有上面的结果,并不是所有的都会这样,我自己的就不是这样的

1. 这是我们假设的在内存中变量的存储情况:

2. 我们现在从循环开始,i = 0, 输入c=0,得到如下结果:

3. 现在i++, i = 1, 输入1,由于输入时会把char当作int来处理,红色框为char的内存加上覆盖到的其他部分内存空间,蓝色框为i的内存空间,如下图:

4. i不断的++,我们输入2, 3, 4,都像上面的情况一样,2, 3, 4都在0x00000000地址的位置存储着,而从0x00000004开始到0x00000010,始终都为0,下面看一下输入4的情况:

如果我们是从终端输入的话,那么这个程序在某些机器上始终让你输入,是个死循环,因为i的值根本就没有发生改变,每次被重新设置为0,循环将一直进行。
但是假设我们是从文件读入的,当读入到4时,就已经是文件末尾了。那么当循环在此执行时,scanf函数不再试图读入新的数值到c,这时,i才可以正常地递增,于是执行printf(),打印出1,如此下去,将打印2, 3, 4。然后程序结束,最终打印的结果就为书上所描述的那种情况:0 0 0 0 0 1 2 3 4。
特别注意,上面所说的都是某些机器上运行的结果,算是一个特例。并不是每个机器上都会运行出那样的结果的

原文地址:http://blog.chinaunix.NET/uid-24807808-id-3335656.html

scanf()接受不同类型的参数的一个例子相关推荐

  1. 使用Zabbix的SNMP trap监控类型监控设备的一个例子

    转载来源 :使用Zabbix的SNMP trap监控类型监控设备的一个例子 :https://www.jianshu.com/p/aa795afdf655 介绍 本文以监控绿盟设备为例. 1.登录被监 ...

  2. 【Zabbix-SNMP trap】使用Zabbix的SNMP trap监控类型监控设备的一个例子

    本文以监控绿盟设备为例. 1.登录被监控的设备的管理系统,配置snmptrap地址指向zabbix服务器或代理服务器. snmptrap地址也叫陷阱. 2.配置或关闭防火墙,并验证是否能在zabbix ...

  3. Postman测试接口传入List类型的参数以及数组类型参数

    Postman测试接口 前言 一.接受List类型的复杂参数 1.列子一.只接受一个List类型: 1.1.列子一.接受一个List类型和Integer类型参数: 2.列子二: 1.1.列子二.接受一 ...

  4. 关于SpringMVC中使用LocalDateTime类型接收参数提示类型不匹配的问题

    解决方法:在形参上前添加注解@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 数据库中的DateTime类型被mybatis逆向工程 ...

  5. C# 关于委托和事件的妙文:通过一个例子详细介绍委托和事件的作用;Observer模式简介...

    委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见 ...

  6. 写一个类Army,代表一支军队,这个类有一个属性Weapon数组w(用来存储该军队所拥有的所有武器), 该类还提供一个构造方法,在构造方法里通过传一个int类型的参数来限定该类所能拥有

    代码 /*开放型题目,随意发挥:写一个类Army,代表一支军队,这个类有一个属性Weapon数组w(用来存储该军队所拥有的所有武器),该类还提供一个构造方法,在构造方法里通过传一个int类型的参数来限 ...

  7. java后台传一个对象到前台_前台判断对象中的一个布尔值_前后台分离的项目中,如何优雅的传输boolean类型的参数...

    前言:需求 这是一个Spring + Angular前后台分离的项目,目前有一个查看作业列表的功能,并且已经设置了分页和几个查询参数,如图. 现在需要增加一个已评阅和未评阅的查询功能. Work实体的 ...

  8. Objective-C 字符串拼接函数 多个不同类型的参数拼接到一个字符串 类似于Java中 String.format()方法的原生API

    总目录 iOS开发笔记目录 从一无所知到入门 文章目录 需求 Screenshot Code Output 需求 我有多个参数(类型也许不同),需要拼接到一个字符串中. 在Java中有String.f ...

  9. Java数据结构习题:编写一个max(),接受首节点作为参数,返回链表中数值最大的结点的值(假设所有数据都是正整数,如果链表为空则返回0)

    编写一个max(),接受首节点作为参数,返回链表中数值最大的结点的值(假设所有数据都是正整数,如果链表为空则返回0) 核心代码: // 编写一个max(),接受首节点作为参数,返回链表中数值最大的结点 ...

  10. SpringMVC如何获取请求带来的各种信息 ||如果我们的请求参数是一个POJO(自定义参数类型), SpringMVC会自动的为这个POJO进行赋值

    SpringMVC如何获取请求带来的各种信息 默认方式获取请求参数: 直接给方法入参上写一个和请求参数名相同的变量.这个变量就来接收请求参数的值: 带:有值,没带:null: 如果我们的请求参数是一个 ...

最新文章

  1. Eclipse 创建 Java 项目概述
  2. AWS — AWS 上的 5G 网络
  3. ORA-07445 [kxsxsi()+450] [SIGSEGV]
  4. FastDFS 学习笔记
  5. 看完微软大神写的求平均值代码,我意识到自己还是 too young 了
  6. while0表示什么意思_什么是意思表示,有哪些形式?
  7. 【Antlr】Antlr语法设计
  8. Python 字符串、列表、字典 操作方法大全 正则re
  9. 简述隐含表法化简状态步骤
  10. Typora使用技巧--不定期更新
  11. 基于群智能的路径规划算法(五)------狼群算法
  12. python写入文件取消自动换行
  13. 磁盘一把锁一个感叹号_Win10系统中如何解决磁盘图标上出现感叹号的情况
  14. mysql 1698_MySql Error 1698(28000)问题的解决方法
  15. Android 获取图片尺寸大小的方法
  16. 手把手教你使用Python批量创建复工证明
  17. P1685 飞跃悬崖
  18. Error loading property file
  19. 在 Kubernetes 上部署 Traefik Ingress
  20. 2018清华计算机考研总结

热门文章

  1. rep( )函数--R语言
  2. 药店药品管理方案,药店药品的盘点方案,假设进行药店药品的高效盘点?药品盘点步骤是?...
  3. Poj 2187 旋转卡壳
  4. 适合iOS的15大网站推荐
  5. WPF-21:WPF实现仿安卓的图案密码键盘(改进)
  6. 使用windows 7有感
  7. C#接口编程实例解析[转]
  8. matlab中modred,计算机仿真技术(中南大学)3系统模型及转换.ppt
  9. java中JFrame.setSize,Java JFrame .setSize(x, y) not working?
  10. java 反射调用方法_Java 反射详解,重要方法解析