在《C陷阱与缺陷》连接(第四章)那一章中,有这样一个程序:
- #include <stdio.h>
- main()
- {
- int i;
- char c;
-
- for(i = 0; i < 5; ++i)
- {
- scanf("%d", &c);
- printf("%d ", i);
- }
- printf("\n");
- }
这是一个关于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。
特别注意,上面所说的都是某些机器上运行的结果,算是一个特例。并不是每个机器上都会运行出那样的结果的
阅读(162) | 评论(0) | 转发(0) |