关于memcpy(),memmove(),strcpy()的小结

memcpy()的实现:

// A C implementation of memcpy()
#include<stdio.h>
#include<string.h>
 
void myMemCpy(void *dest, void *src, size_t n)
{
//此处应加assert(dest != NULL && src != NULL);
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
 
// Copy contents of src[] to dest[]
for (int i=0; i<n; i++)
    cdest[i] = csrc[i];
}
 
// Driver program
int main()
{
char csrc[] = "GeeksforGeeks";
char cdest[100];
myMemCpy(cdest, csrc, strlen(csrc)+1);
printf("Copied string is %s", cdest);
 
int isrc[] = {10, 20, 30, 40, 50};
int n = sizeof(isrc)/sizeof(isrc[0]);
int idest[n], i;
myMemCpy(idest, isrc, sizeof(isrc));
printf("\nCopied array is ");
for (i=0; i<n; i++)
    printf("%d ", idest[i]);
return 0;
}

memcpy有个问题就是当src和dst有重叠时,在copy过程中就会覆盖以后要copy的内容。此时应该用memmove。
下面的代码来自
原文链接:https://blog.youkuaiyun.com/z702143700/article/details/47107701

void* memmove(void* dst,const void* src,size_t count)
{
    assert(NULL !=src && NULL !=dst);
    char* tmpdst = (char*)dst;
    char* tmpsrc = (char*)src;

    if (tmpdst <= tmpsrc || tmpdst >= tmpsrc + count)
    {
        while(count--)
        {
            *tmpdst++ = *tmpsrc++; 
        }
    }
    else
    {
        tmpdst = tmpdst + count - 1;
        tmpsrc = tmpsrc + count - 1;
        while(count--)
        {
            *tmpdst-- = *tmpsrc--;
        }
    }

    return dst; 
}

也可以先从src拷贝到一个临时数组tmp,再从tmp拷贝到dest。不过这个空间复杂度是O(n)。
下面的代码来自
https://www.geeksforgeeks.org/write-memcpy/


//C++ program to demonstrate implementation of memmove()
#include<stdio.h>
#include<string.h>
 
// A function to copy block of 'n' bytes from source
// address 'src' to destination address 'dest'.
void myMemMove(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;
 
// Create a temporary array to hold data of src
char *temp = new char[n];
 
// Copy data from csrc[] to temp[]
for (int i=0; i<n; i++)
    temp[i] = csrc[i];
 
// Copy data from temp[] to cdest[]
for (int i=0; i<n; i++)
    cdest[i] = temp[i];
 
delete [] temp;
}
 
// Driver program
int main()
{
char csrc[100] = "Geeksfor";
myMemMove(csrc+5, csrc, strlen(csrc)+1);
printf("%s", csrc);
return 0;
}

strcpy()只能拷贝字符串,当遇到字符串末尾的NULL(‘\0’)时,它会删除该字符,并结束拷贝。
memcpy()可以拷贝任意类型的字符,不会考虑NULL字符,只拷贝所指定要拷贝的字符数。

一个strcpy的代码例子如下:

void *strcpy(char *strDest, const char *strSrc) {
    assert(strDest != NULL & strSrc != NULL);
    char *addr = strDest;
    while ((*strDest++ = *strSrc++) != '\0');
    return addr;
}
`memcpy` 和 `strcpy` 是 C 语言中常用的两个用于**数据复制**的函数,但它们的用途和使用场景有所不同。 --- ### ✅ `memcpy` 函数 #### 原型: ```c void *memcpy(void *dest, const void *src, size_t n); ``` #### 功能: - 将 `src` 所指内存区域的前 `n` 个字节复制到 `dest` 所指的内存区域。 - 不检查字符串结束符 `\0`,**适用于任意类型的数据复制**(包括字符串、整型数组、结构体等)。 #### 示例: ```c char src[] = "Hello"; char dest[10]; memcpy(dest, src, 6); // 包括 '\0',复制整个字符串 ``` --- ### ✅ `strcpy` 函数 #### 原型: ```c char *strcpy(char *dest, const char *src); ``` #### 功能: - 将 `src` 所指的字符串(包括结尾的 `\0`)复制到 `dest` 中。 - **只用于字符串复制**,遇到 `\0` 结束。 #### 示例: ```c char src[] = "Hello"; char dest[10]; strcpy(dest, src); // 复制字符串 ``` --- ### 🆚 `memcpy` vs `strcpy` | 特性 | `memcpy` | `strcpy` | |---------------------|----------------------------------|----------------------------------| | 数据类型 | 任意内存块 | 仅限于字符串 | | 是否检查 `\0` | 否,复制固定长度 | 是,复制直到遇到 `\0` | | 是否包含 `\0` | 需要手动指定是否复制 | 自动复制 `\0` | | 安全性 | 更灵活但需注意重叠内存问题 | 易造成缓冲区溢出 | | 性能 | 更高效(无需检查 `\0`) | 相对慢一些 | | 使用场景 | 结构体复制、二进制数据复制 | 字符串操作 | --- ### ⚠️ 安全使用建议 - **避免内存重叠**:使用 `memcpy` 时,如果源和目标内存区域有重叠,应使用 `memmove`。 - **防止缓冲区溢出**:使用 `strcpy` 时要确保目标缓冲区足够大,建议使用 `strncpy` 或 `snprintf` 替代。 - **明确复制长度**:使用 `memcpy` 时要确保 `n` 的值正确,特别是处理字符串时是否包含 `\0`。 --- ### ✅ 安全函数推荐 | 原始函数 | 推荐替代函数 | 说明 | |--------------|----------------------|-----------------------------------| | `strcpy` | `strncpy` | 指定最大复制长度,防止溢出 | | `memcpy` | `memmove` | 处理内存重叠的情况 | | `strcat` | `strncat` | 安全拼接字符串 | | `sprintf` | `snprintf` | 控制最大写入长度,防止溢出 | --- ### 💡 示例对比 #### 使用 `strcpy`(不安全): ```c char dest[5]; strcpy(dest, "Hello, world!"); // 缓冲区溢出 ``` #### 使用 `strncpy`(更安全): ```c char dest[5]; strncpy(dest, "Hello, world!", sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0'; // 手动添加结束符 ``` #### 使用 `memcpy`(适合结构体或二进制数据): ```c typedef struct { int id; char name[20]; } User; User user1 = {1, "Alice"}; User user2; memcpy(&user2, &user1, sizeof(User)); // 安全复制结构体 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值