数组下标越界(Index out of bounds)对初学者来说是很易犯的错误。先来看数组下标越界的例子。
1 #include <stdio.h> 2 int main(void) 3 { 4 int i, a, s[5], b; 5 6 printf("%p %p %p ", &a, s, &b); 7 a = b = 1; 8 9 for(i = -1; i <= 5; i++) 10 s[i] = 2; 11 printf("%d %d %d %d ", a, s[0], s[4], b); 12 13 return 0; 14 }
程序输出如下
0022FF48 0022FF34 0022FF30
2 2 2 2
存储空间图示如下,可以看到b恰好在数组的前面,而a正好在数组的后面。
s[i]=*(s+i), 所以s[-1]正好是b,s[5]正好是a。而-1,5两个下标不在数组的有效下标中。在现实中经常可以看到编程人员控制不好s[i]中的i, 导致i越界,有些语言(如Java)运行时刻会对此进行检查,但是C不会。
缓冲区溢出(buffer overflow, or buffer overrun)是指写数据到缓冲区(很多情况可以看成数组)时,越过缓冲区的边界写入其邻接的存储区域的现象。
1 #include <stdio.h> 2 int main(void) 3 { 4 char a, s[5], b; 5 6 a = b = '@'; 7 gets(s); 8 printf("%p %p %p ", &a, s, &b); 9 printf("%c %s %c ", a, s, b); 10 11 return 0; 12 }
输入下面的内容
abcdefg
程序的输出如下
0022FF4F 0022FF4A 0022FF49
f abcdefg @
存储空间图示如下,字符数组s容纳不下"abcdefg", 字符a的内容被重写成了f。
可以看到,gets没有检查数组的边界,放任多余的内容写到了数组s的邻接区域。你可以尝试输入更多的数据,看看有什么情况会发生。
以上代码的输出均在CodeBlocks 13.12平台上产生。