Chinaunix首页 | 论坛 | 博客
  • 博客访问: 601009
  • 博文数量: 68
  • 博客积分: 2621
  • 博客等级: 少校
  • 技术积分: 1498
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 21:04
文章分类

全部博文(68)

文章存档

2013年(8)

2012年(52)

2010年(8)

分类: C/C++

2012-09-03 09:51:14

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

点击(此处)折叠或打开

  1. #include <stdio.h>

  2. main()
  3. {
  4.     int i;
  5.     char c;
  6.     
  7.     for(i = 0; i < 5; ++i)
  8.     {
  9.         scanf("%d", &c);
  10.         printf("%d ", i);
  11.     }

  12.     printf("\n");
  13. }
    这是一个关于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()就会返回EOF,不会改变内存中的变量。于是执行printf(),打印出1,如此下去,将打印2, 3, 4。然后程序结束,最终打印的结果就为书上所描述的那种情况:0 0 0 0 0 1 2 3 4。

    特别注意,上面所说的都是某些机器上运行的结果,算是一个特例。并不是每个机器上都会运行出那样的结果的
阅读(3823) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~