题目是这样的:
下面的程序会出现何种问题?
#include<iostream>
#include<stdio.h>
int main()
{
char s[] = "123456789";
char d[] = "1234";
strcpy(d,s);
printf("%s,\n%s",d,s);
return 0;
}
刚看这个题目的时候,得出的 结果是123456789,123456789.看了好多次题目的解答都没看明白。仔细研究了一下,发现自己还是有很多问题不会的。
1、变量的内存分配
变量定义之后,要分配内存,一般情况是先定义的变量分配到高地址,后定义的分配到低地址。比如先定义s[],后定义d[],s就在高地址,d就在低地址。还有一点很重要,系统在给char[]类型分配内存的时候,是对齐的,也就是说,当给变量分配内存时,遇到不能占满整个字的,要分配给变量整个字的大小。比如,操作系统是32位的,在给变量分配内存的时候,最小的分配单位是32位,也就是4个字节。当变量占有1个字节的时候,也会给变量分配4个字节。
2、strcpy函数在拷贝的时候,要求dest的空间要足够能装下source,否则会报错。
3、在读取字符串的时候,每当遇到\0,就结束读取。
我们看一下这个题目。题目中先定义的是s,所以s在高地址,d在低地址。内存分配如下所示:
内存地址 内容
d 0x0030 1234
0x0034 \0
s 0x0038 1234
0x003c 5678
0x0040 9\0
当拷贝的时候,s中的内容会覆盖掉d中的内容,并且会占用s的内存,这时候系统是不会报错的,因为s的内存已经分配。拷贝后结果如下:
内存地址 内容
d 0x0030 1234
0x0034 5678
s 0x0038 9\034
0x003c 5678
0x0040 9\0
最后打印的结果为s:9,d:123456789.如果定义的顺序相反,内存分配结果如下:
内存地址 内容
s 0x0030 1234
0x0034 5678
0x0038 9\0
d 0x003c 1234
0x0040 \0
当拷贝的时候,就出现问题了,因为s要覆盖掉d中的内容,但是,d的空间不够,拷贝的时候,使用到了没有分配的空间,这时候会出现问题。在vs6.0中运行时,会输出s:123456789,d:123456789同时会提示错误。
知道以上说的三点,这个题目就很容易解决了。