写C程序的时候经常会用到读字符串。当为字符串数组开辟的空间不够大的时候,输入字符数大于数组大小会发生不可预知的运行时的错误,这种错包括1> 运行时错误,2>结果错误,3,>段错误。遗憾的是C语言本身没有提供检测这种的错误的机制。下面根据代码分析产生错误的类型以及原因。
分析1
#include <stdio.h> int main(void) { int sum = 0, i = 0; char input[5]; while (1) { sum = 0; scanf("%s", input); for (i = 0; input[i] != '\0'; i++) sum = sum*10 + input[i] - '0'; printf("input=%d\n", sum); } return 0; }若输入1234567,输出为1234567;
上面代码,若输入12345678会输出123456740。
为什么会出现123456740,而不是输出12345678呢?如果了解函数栈结构我们会指导 i 的地址就是input[8]的地址。当循环进行八次之后i=8,input[8]=0x08;经过这样的运算12345678*10+8-48,得到1234456740。当然得到这个值也取决于机器的字节存放顺序,是大端法还是小短发,得出这样的结果也证明本机是采用的是大端法。若是小端法会得到另外一种结果。
分析2
#include <stdio.h> int main(void) { int sum = 0, i = 0; char input[5]; while(1) scanf("%s", input); for (i = 0; input[i] != '\0'; i++) { if (input[i] < '0' || input[i] > '9') { printf("Invalid input!\n"); sum = -1; break; } sum = sum*10 + input[i] - '0'; } printf("input=%d\n", sum); } return 0; }运行./main
输入12345678
输出Invalid input!
解释见分析一。不会产生段错误。
分析3
若把分析2代码中while循环去掉,再输入12345678901234567,17个数字会超过main函数中sum的地址的范围,会发生段错误。
但是在代码2中输入这17个数字则不会产生段错误?这是为什么呢?这是因为如果某个函数的局部变量发生访问越界,有可能并不立即发生段错误,而是在函数返回的时候发生段错误。