关于strcpy()函数在拷贝字符串数组的时候出现的大小不匹配问题和数组值改变问题

问题的来源是自己写的一个测试代码:

#include <iostream>
using namespace std;

int main() {
    char a[1];
    a[0] = 'a';
    a[1] = 'b';

    char b[1];
    b[0] = 'c';
    b[1] = 'd';

    strcpy(a, b);
    cout<<"拷贝之后:a[0] = "<<a[0]<<"    a[1] = "<<a[1]<<endl;
    cout<<"拷贝之后:b[0] = "<<b[0]<<"    b[1] = "<<b[1]<<endl;
    return 0;
}

在这之后输出的两个字符串的值并不是想象中的:

“拷贝之后:a[0] = c  a[1] = d

 拷贝之后:b[0] = c  b[1] = d”

而是:

一开始看到之后一脸懵逼,为啥我用strcpy()拷贝完之后,源字符数组的值反而不对了呢?

于是我多写了一些测试用的输出代码,和显示两个字符数组头在内存中位置的输出代码来找出问题所在:

#include <iostream>
using namespace std;

int main() {
    char a[1];
    a[0] = 'a';
    a[1] = 'b';
    cout<<"a[0] = "<<a[0]<<"    a[1] = "<<a[1]<<endl;

    char b[1];
    b[0] = 'c';
    b[1] = 'd';
    cout<<"声明char b[1]后:a[0] = "<<a[0]<<"    a[1] = "<<a[1]<<endl;
    cout<<"b[0] = "<<b[0]<<"    b[1] = "<<b[1]<<endl;

    strcpy(a, b);
    printf("%x\n",a);
    printf("%x\n",b);
    cout<<"拷贝之后:a[0] = "<<a[0]<<"    a[1] = "<<a[1]<<endl;
    cout<<"拷贝之后:b[0] = "<<b[0]<<"    b[1] = "<<b[1]<<endl;
    return 0;
}

随后得到了输出如下:

可见,在声明完char b[1]这个小婊砸后,字符数组a中的值就已经被改变了!

这是为什么呢?

可以看到,a和b这两个字符数组的地址相差只有1,这也就是问题的所在了!

在刚声明完char a[1]时,内存中是这样的:

53151adb  'a'   // 这里是字符数组a的开始地址

53151adc  'b'

53151add  '\0'

而等到char b[1]声明完后,内存中变成了这样:

53151ada  'c'   // 这里是字符数组b的开始地址

53151adb  'd'   // 这里是字符数组a的开始地址,原来的 'a' 被字符数组b中的 'd' 覆盖了!

53151adc  '\0'  // 原来的'b'被字符数组b中的结尾符'\0'覆盖了!

53151add  '\0'

这就解释了为什么char b[1]声明完后,a[1]变成了'd'的问题。

那么当我们使用了strcpy(a, b)会怎么样呢?

这个函数会把b中的值一个个复制到a中去,因此复制完之后内存地址长这样:

53151ada  'c'   // 这里是字符数组b的开始地址

53151adb  'c'   // 这里是字符数组a的开始地址,刚刚的 'd' 被字符数组b中的 'c' 覆盖了!

53151adc  'd'   // 刚刚的'\0'被字符数组b中的'd'覆盖了!

53151add  '\0'

这时候,再输出字符数组a和b的时候,就呈现了一开始我们看到的一坨&%&%¥%@……嗯。

欢迎大家在评论区留言交流~

posted @ 2016-12-10 03:09  Aaroooon  阅读(2275)  评论(0编辑  收藏  举报