接着上一篇的步骤,经过调试我们知道,虽然sum已经赋了初值0,但仍需要在while (1)循环的开
头加上sum = 0;:
观察点调试实例:
#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;
}
使用scanf函数是非常凶险的,即使修正了这个Bug也还存在很多问题。如果输入的字符串超长了会怎么样?我们知道数组访问越界是不会检查的,所以scanf会写出界。现象是这样的:
[zhangsan@localhost study-c]$ gcc -Wall -g gdb3.c -o gdb3
[zhangsan@localhost study-c]$ ./gdb3
123
input=123
1234
input=1234
12345
input=12345
123456
input=123456
1234567
input=1234567
12345678
input=1912370802
可是奇怪的是当我们输入1234567的时候,字符串也超长了呀,为什么没有错误发生呢?这个问题现在也无法搞清楚?
下面用调试器看看最后这个诡异的结果是怎么出来的:
[zhangsan@localhost study-c]$ gdb gdb3
GNU gdb (GDB) 7.6.1
...
Reading symbols from /home/zhangsan/study-c/gdb3...done.
(gdb) start
Temporary breakpoint 1 at 0x40053c: file gdb3.c, line 5.
Starting program: /home/zhangsan/study-c/gdb3
Temporary breakpoint 1, main () at gdb3.c:5
5 int sum = 0, i = 0;
(gdb) n
9 sum = 0;
(gdb)
10 scanf("%s",input);
(gdb)
12345678
11 for(i = 0;input[i] != '\0'; i++)
(gdb) print input
$1 = "12345"
input数组只有5个元素,写出界的是scanf自动添的'\0',用x命令看会更清楚一些:
(gdb) x/10b input
0x7fffffffe4f0: 49 50 51 52 53 54 55 56
0x7fffffffe4f8: 0 0
x命令打印指定存储单元的内容。10b是打印格式,b表示每个字节一组,10表示打印10组,从input数组的第一个字节开始连续打印10个字节。前8个字节是input数组的存储单元,打印的正是十进制ASCII码的'1'到'8',第9个字节是写出界的'\0'。根据运行结果,前7个字符转成数字都没错,第8个错了,也就是i从0到6的循环