代码改变世界

转:一个strcpy的问题(很容易做错)

2013-09-28 02:26  youxin  阅读(835)  评论(0编辑  收藏  举报

下面的执行结果是什么?

#include<stdio.h>
#include<string.h>
void main()
{
char s[]="123456789";
char d[]="123";
strcpy(d,s);
printf("d=%s,\ns=%s",d,s);
}

执行结果:d=56789,

                  s=123456789

书上有关于这个的解答,说是因为当初分配的内存地址是连续内存的问题, 
原来的是1234\0123456789\0,strcpy后变成123456789\06789\0。

分析:首先要解释一下,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[]的起始位置。 
          所以此时输出的是s的值是 '5' '6' '7' '8' '9' '\0'。

这个题目出的很好,一方面考查了栈的生长方向,另一方面考查了strcpy的具体细节。

如果 

 

char d[]="12", 

char d[]="1" 答案是什么呢?

执行结果依旧是:d=56789,

 

                             s=123456789

 

                 '1' '2' '\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' 

 

这里就考虑对齐的问题,一般来说是4位一对齐。如果超过4位,就是8位一对齐

 

char s[]="123456789";
char d[]="12";
printf("%p    %p    %p    %p",d,d+1,d+2,d+3);
 
printf("\n%p \n",s);

printf("%d\n",d[2]);

运行输出:

0012FF38 0012FF39 0012FF3A 0012FF3B
0012FF3C
0 字符串结束符

Key看到d[3]是不存的。char d="12"占了4位。

 

如果 

char d[]="1234", 

char d[]="12345"

执行结果依旧是:d=9,

                             s=123456789

 

                 '1' '2' '3' ‘4’  \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' 

 输出:

123456789

9

 看另一程序.

 

#include<stdio.h>
#include<string.h>
void main()
{
   char d[]="123";

char s[]="123456789";
strcpy(d,s);
printf("d=%s,\ns=%s",d,s);
}

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

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

 参考:http://www.cnblogs.com/aquariusgx/archive/2011/02/16/1956320.html