使用的编辑器:visual studio 2013
下面两段代码test1和test2,test1是对数组进行了初始化,而test2没有定义长度:
#include <stdio.h>
#include <string.h>
void test1();
void test2();
void main() {
test1();
test2();
}
void test1(){
char s[11] = "wgwe123";
char s2[11] = "";
strcpy(s2, s);
//strcpy_s(s2,strlen(s)+1 ,s);
int i = 0;
for (int j = 0; j < strlen(s2); j++){
printf("s[%d] = %c,length = %d\n", j, s2[j], strlen(s2));
}
printf("*****************************\n");
while (s[i] !='\0'){
printf("s[%d] = %c,length = %d\n", i, s[i],strlen(s));
++i;
}
printf("s2 = %s,length = %d\n", s2,strlen(s2));
}
void test2(){
char s[11] = "wgwe123";
char s2[] = "";
strcpy(s2, s);
//strcpy_s(s2,strlen(s)+1 ,s);
int i = 0;
for (int j = 0; j < strlen(s2); j++){
printf("s[%d] = %c,length = %d\n", j, s2[j], strlen(s2));
}
printf("*****************************\n");
while (s[i] !='\0'){
printf("s[%d] = %c,length = %d\n", i, s[i],strlen(s));
++i;
}
printf("s2 = %s,length = %d\n", s2,strlen(s2));
}
然而,test1和test2的运行结果和想象的完全不一样(test1是进行了数组的初始化,而test2没有)test1的结果是:
s2[0] = w,length = 7
s2[1] = g,length = 7
s2[2] = w,length = 7
s2[3] = e,length = 7
s2[4] = 1,length = 7
s2[5] = 2,length = 7
s2[6] = 3,length = 7
**************************
s[0] = w,length = 7
s[1] = g,length = 7
s[2] = w,length = 7
s[3] = e,length = 7
s[4] = 1,length = 7
s[5] = 2,length = 7
s[6] = 3,length = 7
s2 = wgwe123,length = 7
test2的结果是:
s2[0] = w,length = 7
s2[1] = g,length = 7
s2[2] = w,length = 7
s2[3] = e,length = 7
s2[4] = 1,length = 7
s2[5] = 2,length = 7
s2[6] = 3,length = 7
************************
s[0] = g,length = 6
s[1] = w,length = 6
s[2] = e,length = 6
s[3] = 1,length = 6
s[4] = 2,length = 6
s[5] = 3,length = 6
s2 = wgwe123,length = 7
显然test1的结果是正确的,test2的结果是错误的,是因为s2数组初始化没有设置长度(当然这本身就是不对的)
问题是:输出的结果:s2也成功被复制了,s 的内容却发生了变化,为什么初始数组会发生变化呢再来:
void test3(){
char s[11] = "wgwe123";
char s2[] = "aaa";
strcpy(s2, s);
//strcpy_s(s2,strlen(s)+1 ,s);
int i = 0;
for (int j = 0; j < strlen(s2); j++){
printf("s[%d] = %c,length = %d\n", j, s2[j], strlen(s2));
}
printf("*****************************\n");
while (s[i] !='\0'){
printf("s[%d] = %c,length = %d\n", i, s[i],strlen(s));
++i;
}
printf("s2 = %s,length = %d\n", s2,strlen(s2));
}
结果是:
s2[0] = w,length = 7
s2[1] = g,length = 7
s2[2] = w,length = 7
s2[3] = e,length = 7
s2[4] = 1,length = 7
s2[5] = 2,length = 7
s2[6] = 3,length = 7
************************
s[0] = 1,length = 3
s[1] = 2,length = 3
s[2] = 3,length = 3
s2 = wgwe123,length = 7
s2被赋值成功了,s变成了123,查看strcpy的源码:
char * strcpy(char *dst,const char *src)
{
assert(dst != NULL && src != NULL);
char *ret = dst;
while ((*dst++=*src++)!='\0');
return ret;
}
源码是没问题的,那就考虑内存占用问题了,实际上,如果没有对s2进行初始化,那么s2系统只给他分配了一个字节的空间保存数组的\0,那么对s2进行拷贝的时候,很有可能会把s的内存空间占用,而如果s2开始就分配了内存的话这种情况是不存在的。打印内存如下:
拷贝前:s 地址为: 8ffe84, s2 地址为: 8ffe83
拷贝后:s 地址为: 8ffe84, s2 地址为: 8ffe83
s2的首地址分配是在s前面的,所以对s2进行赋值的时候,s1的内存必然会被占用,果然刚好占用了一个字节,如下图所示:
当对s2进行拷贝的时候,s的内存被占用,如下图所示:
因此,输出的s从首地址8ffe84开始到'\0'结束,为:gwe123
s2的从首地址8ffe83开始到'\0'结束,为:wgwe123