字符串越界问笔试常见题
1、
#include<string.h> int main() { char string[10]; // 甚至 string[9]都可以 int i; char *str1="0123456789"; // 这里实际还要添加 '\0',因为 \0是C++中字符串的结尾标志,存储在字符串的结尾。比如char cha[5]表示可以放4个的数组,由于c/c++中规定字符串的结尾标志为'\0',它虽然不计入串长,但要占内存空间 strcpy(string,str1); // 相当于把 0123456789 还有 '\0' 共 11个字符存入 10个中,放不下只好越界,况且C语言编译器是不检查越界的</span>
for( i=0;i<10;i++) printf("%c",string[i]); printf("\n"); printf("%c",str1[10]); }
strcpy()函数是对C风格字符串进行操作的函数,
上例的str1是一个字符串,C风格的字符串以‘\0’结束,
所以str1虽然看上去只有10个字符,但实际上应加上‘\0’,即应为11个字符,
而string数组只有10个元素,而strcpy()函数的实现是遇'\0'而停止拷贝,所以拷贝时实际上是把‘\0’也进行了拷贝,这就导致string数组越界拷贝
当然有时候运行正常,有时候是不正常的,这取决于 越界后后面的 string[10],对程序有没有危险。
注意: strcpy()函数是多C风格的字符串进行拷贝,即遇‘\0’而停止拷贝
——————————————————————————————————————————————————————————————
2、
#include<stdio.h> #include<string.h> int main() { char string[10], str1[10]; int i; for(i=0; i <10;i++) { str1[i] = 'a'; } printf("%d\n",&str1[10]); // 这个地址在内存里是 1245042,也就是 str1[10]的地址,当然str1[10]坑定算越界了, printf("%c\n",*(char *)1245042); // 这里用 指向 char类型的指针来 查找 str1[10]里面究竟存的是什么,这里存的是'?' // 当然 1245041 存的是 a strcpy(string, str1); for( i=0;i<10;i++) printf("%c",string[i]); printf("\n"); printf("%c",str1[10]); } // //上例说过strcpy()函数是多C风格的字符串进行拷贝,即遇‘\0’而停止拷贝,而本例中str1不是C风格的字符串,而是一个char数组, //不是以'\0'结束的,所以strcpy()函数会一直进行拷贝直到遇到第一个'\0'才结束拷贝,所以string越界是必然的,因为我们不知道什么时候遇到'\0'。
运行不起来
————————————————————————————————————————————————————————————————————
3、
#include<stdio.h> #include<string.h> int main() { char *str1="123456789" ; //指针字符串的好处是 会自动添加 字符串结束符 '\0',也就是正好 10 个数了 char string[10]; if(strlen(str1) <10) // strlen 计算的是有效可见的字符长度,自然'\0'是不算的,所以这里为 9 ,10个放10个没有问题 { strcpy(string, str1); } printf("%s",string); }
但是如果把 char *str1="123456789" 改为 0123456789 ,那么就是10个字符再加上 '\0' 共11个字符
,那么就错了。
————————————————————————————————————————————————————————————————————————————————