strcpy拷贝越界问题

来源:互联网 发布:数据完整性保护 编辑:程序博客网 时间:2024/05/17 10:06

《strcpy拷贝越界问题》

一. 程序一

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. void main()  
  4. {  
  5.  char s[]="123456789";  
  6.  char d[]="123";  
  7.  strcpy(d,s);  
  8.  printf("d=%s,\ns=%s",d,s);  

执行结果:

解释:

首先要解释一下,char s[]="123456789"; char d[]="123"; 这样定义的数组和变量存放在栈内存中。 
栈内存是一个自顶向下分布的数据结构,那么越先定义的变量地址就越高,越后定义的地址就越低。 
s比d定义在前,那么s得到了高地址,而d得到了相对低的地址,那么内存中的存放形式就是 
d[] <- | -> s[] 
'1' '2' '3' '\0' | '1' '2' '3' '4' '5' '6' '7' '8' '9' '\0' 
字符串拷贝后: 
'1' '2' '3' '4 ' | '5' '6' '7' '8' '9' '\0' '7' '8' '9' '\0' 
中间的‘|’表示s[]的起始位置。 
所以此时输出的是d的值是 '1' '2' '3' '4' '5' '6' '7' '8' '9' '\0's的值是 '5' '6' '7' '8' '9' '\0'

 

二. 程序二

  1. #include<stdio.h>  
  2. #include<string.h>  
  3. void main()  
  4. {  
  5.   char d[]="123";  
  6.  
  7.  char s[]="123456789";  
  8.  strcpy(d,s);  
  9.  printf("d=%s,\ns=%s",d,s);  
  10. }  

运行结果:

说明:

虽然可以看到正确的输出结果d=123456789,s=123456789执,但是产生运行错误!

这是因为字符串拷贝后,越过了目标字串的实际空间,访问到了不可预知的地址了。

三. strcpy函数原型

  1. //已知strcpy函数的原型是:  
  2. char * strcpy(char * strDest,const char * strSrc);  
  3.  
  4.  
  5. //实现代码  
  6. char * strcpy(char * strDest,const char * strSrc)  
  7. {  
  8. if ((strDest==NULL)||(strSrc==NULL))  
  9.  
  10. throw "Invalid argument(s)";   
  11.  
  12. char * strDestCopy=strDest;   
  13.  
  14. while ((*strDest++=*strSrc++)!='\0');   
  15.  
  16. return strDestCopy;  
  17. }  

 最重要一条语句为:while ((*strDest++=*strSrc++)!='\0') ,意思是先将第二参数当前指针所指内容赋值给第一个参数当前指针所指空间,直到第二参数当前指针所指内容为'\0',将'\0'赋值给第一个参数后结束,因为第一个参数当前指针也是不断自加的,跟第一个参数所具有的存储空间的大小没有关系,他们会一直赋值,超过第一参数存储空间也没有关系,直到第二参数遇到'\0'为止。


3个小例子说明下strcpy()与数组越界

 (2012-08-07 10:40:45)
转载
标签: 

数组越界

 

it

 分类: C/C 总结

1

Void test1()
{
char string[10]; //甚至string[9]都可以!
char *str1= "0123456789 ";
strcpy(string, str1);
}
数组越界

strcpy()函数是对C风格字符串进行操作的函数,上例的str1是一个字符串,C风格的字符串以‘\0’结束,所以str1虽然看上去只有10个字符,但实际上应加上‘\0’,即应为11个字符,而string数组只有10个元素,而strcpy()函数的实现是遇'\0'而停止拷贝,所以拷贝时实际上是把‘\0’也进行了拷贝,这就导致string数组越界拷贝。
--------------------------------------------------------------------------
2

Void test2()
{
char string[10], str1[10];
for(i=0; i <10;i++)
{
str1[i] = 'a ';
}
strcpy(string, str1);
}
数组越界

如例1,上例说过strcpy()函数是多C风格的字符串进行拷贝,即遇‘\0’而停止拷贝,而本例中str1不是C风格的字符串,而是一个char数组,不是以'\0'结束的,所以strcpy()函数会一直进行拷贝直到遇到第一个'\0'才结束拷贝,所以string越界是必然的,因为我们不知道什么时候遇到'\0'。
--------------------------------------------------------------------------
3.
Void test3(char* str1)
{
char string[10];
if(strlen(str1) <=10)
{
strcpy(string, str1);
}
}
==数组越界

本例str1是一个字符串指针,这里就要说到strlen()函数了,strlen()是计算C风格字符串字符长度的函数,虽然说是计算字符长度,但是实际上计算的只是有效可见字符长度,即不计算'\0',所以本例中如果strlen(str1)计算的长度为10的时候事迹上str1是11个字符,所以拷贝时同样会出现11个字符拷贝到string数组中的情况发生,即会数组越界。

    通过上面三个小例子简单介绍了数组越界的问题,以及C风格字符串部分函数的使用:数组越界时编辑器不会报错,编译器不检查数组越界,strcpy()函数是针对C风格字符串进行拷贝的,即遇'\0'而停止拷贝,strlen()函数只拷贝字符串的实际显示的字符长度,而不包括'\0'字符,所以使用时,可能会因为不注意而出错。这里的介绍也不是很全面,只是遇到了就写一下而已。


0 0