看一个程序,这个程序在执行时会出现无限循环:
#include<stdio.h>
#include<conio.h>
void main()
{
char c;
FILE *fp;
if((fp=fopen("c://wlj.cpp","r"))==NULL)
printf("error");
while((c=fgetc(fp))!=NULL) /*while((c=fgetc(fp))!=EOF) */
printf("%c",c);
fclose(fp);
c = 255;
printf("%d %d",sizeof(short),c);
getch();
}
分析:
1. 这个程序在执行会出现死循环,因为文件结尾会返回EOF=-1,而NULL被定义为0或 0L 或((void *)0),所以正确的NULL改为EOF。
参考:
在/Vc7/include/stdio.h中
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/**/
#define EOF (-1)
在/TC/include/stdio.h中
/**/
#ifndef NULL
#if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
#define NULL 0
#else
#define NULL 0L
#endif
#endif
/* End-of-file constant definition
*/
#define EOF (-1) /* End of file indicator */
2. 在TC2.0、TC3.0和VC7.0中单步调试代码时可以设定观察变量c和(int)c,可以发现遇到回车换行符是读出的c=’/n’, (int)c=10,即ASCII中的LF(line feed),且仅仅是一个LF字符,没有CR (13)字符,这在写给文本加解密的程序时时要注意的,大二时写过对txt文件用异或算法加解密的程序,但是后来却发现解密(还原)后的文件有乱码,其实就是对回车换行符处理出了错误。
3. 遇到EOF字符时结果有些不同:
| c | (int)c |
TC2.0 | ‘ ‘ | -1 |
TC3.0 | ‘ ‘ | 255 |
VC7.0 | ‘ ‘ | -1 |
由此可以看出,在三种环境中char类型有类似如下的定义
TC2.0 | #define char signed short |
TC3.0 | #define char unsigned short |
VC7.0 | #define char signed byte |
4. getc不可能返回NULL(0)字符。
5. 此程序的最开始版本是
#include<stdio.h>
#include<conio.h>
void main()
{
char a[1000],c;
int i=0,j;
FILE *fp;
if((fp=fopen("c://my.cpp","r"))==NULL)
printf("error");
while((c=fgetc(fp))!=NULL) a[i++]=c;
for(j=0;j<=i-1;j++) printf("%c",a[j]);
fclose(fp);
getch();
}
这样的话程序更容易出错,因为boldfaced代码行出现无限循环时,数组a会出现越界,而C/C++没有数组越界检查,这样会造成内存的错误使用而使程序非法终止。