关于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的时候,就呈现了一开始我们看到的一坨&%&%¥%@……嗯。

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

时间: 2024-08-05 12:20:15

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

通过编写字符复制函数strcpy函数学编程

首先我们先来开一下标准函数中的strcpy长什么样子 C语言标准库函数strcpy,把从src地址开始且含有'\0'结束符的字符串复制到以dest开始的地址空间. 原型声明:char *strcpy(char* dest, const char *src); 头文件:#include <string.h> 和 #include <stdio.h> 功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间 说明:src和dest所指内存区域不可以重叠且des

C语言--strcpy()函数

strcpy,即string copy(字符串复制)的缩写. strcpy是一种C语言的标准库函数,strcpy把含有''\0'结束符的字符串复制到另一个地址空间,返回值的类型为char*. C语言 strcpy() 函数用于对字符串进行复制(拷贝). 头文件:string.h 语法/原型: char* strcpy(char* strDestination, const char* strSource); 参数说明: strDestination:目的字符串. strSource:源字符串.

字符数组拷贝与strcpy函数

代码: char str1[10],str2[10]; for (int i=0;i<10;i++) { str1[i]='a'; } strcpy(str2,str1); 让找出错误的地方. 先来看下strcpy函数: 使用格式:char* strcmp(char* buffer,char*str)功 能: 把从str地址开始且含有NULL结束符的字符串复制到以buffer开始的地址空间,buffer地址空间中必须有足够的空间来容纳str的字符串. 转自此文 所以上面代码错误的地方就是str1

strcmp函数和strcpy函数

(一)strcmp函数 strcmp函数是比較两个字符串的大小,返回比較的结果.一般形式是: i=strcmp(字符串,字符串); 当中,字符串1.字符串2均可为字符串常量或变量:i   是用于存放比較结果的整型变量.比較结果是这样规定的: ①字符串1小于字符串2,strcmp函数返回一个负值; ②字符串1等于字符串2,strcmp函数返回零; ③字符串1大于字符串2,strcmp函数返回一个正值;那么,字符中的大小是怎样比較的呢?来看一个样例. 实际上,字符串的比較是比較字符串中各对字符的AS

memcpy、memmove、memset及strcpy函数实现和理解

memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h>, 在C++中需要包含的头文件是#include其函数原型如下: void *memcpy(void *dest, const void *src, size_t n); 其功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. 库函数中的memcpy不能处理sr

c语言常用函数strcmp函数和strcpy函数

(一)strcmp函数 strcmp函数是比较两个字符串的大小,返回比较的结果.一般形式是: i=strcmp(字符串,字符串); 其中,字符串1.字符串2均可为字符串常量或变量:i   是用于存放比较结果的整型变量.比较结果是这样规定的: ①字符串1小于字符串2,strcmp函数返回一个负值; ②字符串1等于字符串2,strcmp函数返回零; ③字符串1大于字符串2,strcmp函数返回一个正值;那么,字符中的大小是如何比较的呢?来看一个例子. 实际上,字符串的比较是比较字符串中各对字符的AS

memcpy函数、strcpy函数、strncpy函数

一.函数说明 1.memcpy函数 void  *memcpy(void *s1,  const void *s2,  size_t  n); 说明: 函数memcpy从s2指向的对象中复制n个字符到s1指向的对象中.如果复制发生在两个重叠的对象中,则这种行为未定义. 返回值: 函数memcpy返回s1的值. 2.strcpy函数 char  *strcpy(char *s2, const char *s1); 说明: 函数strcpy把s1指向的串(包括空字符)复制到s2指向的数组中.如果复制

写一个函数,将字符串中空格替换为%20。

写一个函数,将字符串中空格替换为%20.样例:"abc defgx yz"替换为"abc%20defgx%20yz".这道题是一道简单的字符和字符串替换题,字符的替换直接用指针即可,每次都需要把空格后的字符串保存到一个数组中,然后把空格替换为%20后再将刚刚拷贝的字符串拷贝到%20的后面,代码如下: Fun(char str){char p = str;char arr[20];while (p != '\0'){if (p == ' '){strcpy(arr,

strcpy函数的实现

大家一般觉得名不见经传strcpy函数实现不是非常难,流行的strcpy函数写法是: char *my_strcpy(char *dst,const char *src) { assert(dst != NULL); assert(src != NULL); char *ret = dst; while((* dst++ = * src++) != '\0') ; return ret; } 假设注意到: 1,检查指针有效性: 2,返回目的指针des: 3,源字符串的末尾 '\0' 须要拷贝.