scanf函数可变参数部分要求输入地址,这说明scanf函数对它们进行的是间接访问,这样在%s字符串和%mc宽度格式输入过程中可能产生内存越界问题,如下面的测试程序:
1、%s字符串内存越界测试程序
#include < stdio.h>
int main(void)
{
char b[5]={};
char a[5]={};
int i;
scanf("%s", a);
printf("a(%p)\tb(%p)\n", a, b);
for(i=0; i<5; i++)
{
printf("%c(%p)\t", a[i], &a[i]);
printf("%c(%p)\n", b[i], &b[i]);
}
return 0;
}
输入:
12345678
结果:
a(0xbf961bf2)b(0xbf961bf7)
1(0xbf961bf2)6(0xbf961bf7)
2(0xbf961bf3)7(0xbf961bf8)
3(0xbf961bf4)8(0xbf961bf9)
4(0xbf961bf5)(0xbf961bfa)
5(0xbf961bf6)(0xbf961bfb)
从结果看当scanf以%s字符串格式输入超过数组a[5]范围时,会发生内存越界,这样就到了数组b[5]里面。这样的后果是a[5]里的数据也不能看做字符串,因为不是以\0结尾的,同时当我们在b[5]里存有重要数据,这种内存越界发生时,会出现莫名其妙的程序运行结果。
2、%mc宽度内存越界测试程序
#include < stdio.h>
int main(void)
{
char a[5]={};
int i;
scanf("%3c%2c", &a[1], &a[0]);
for(i=0; i<5; i++)
{
printf("a[%d](%p) = %c\n", i, &a[i], a[i]);
}
return 0;
}
输入:
12345
输出:
a[0](0xbfc24ae7) = 4
a[1](0xbfc24ae8) = 5
a[2](0xbfc24ae9) = 2
a[3](0xbfc24aea) = 3
a[4](0xbfc24aeb) =
从结果看%mc宽度格式输入时,scanf函数并没有把多余的两个字符丢掉,而是存储在连续的地址空间,这样的结果是没有按照我们预想的结果输出,字符1被字符5覆盖了。