内存操作函数详解

一:memcpy函数及实现

用于在内存中复制数据块。函数原型定义在 <string.h> 头文件中。其基本用法如下:

void *memcpy(void *dest, const void *src, size_t n);

这个函数的功能是从源(src)所指向的内存地址开始复制 n 个字节到目标(dest)所指向的内存地址。memcpy 函数会返回目标内存区域的指针。

以下是 memcpy 函数的参数说明:

  • dest:指向复制数据的目标内存地址的指针。
  • src:指向要复制的数据源内存地址的指针。
  • n:要复制的字节数。

使用 memcpy 时需要注意以下几点:

  1. memcpy 函数不会检查源和目标内存区域是否有重叠如果源和目标内存区域重叠,使用 memcpy 可能会导致未定义的行为。在这种情况下,应该使用 memmove 函数,它会正确处理重叠区域。
  2. 使用 memcpy 时,确保目标内存区域有足够的空间来容纳源数据,以避免缓冲区溢出。

 示例:

#include <stdio.h>
#include <string.h>

int main() {
    char src[50] = "Hello, World!";
    char dest[50];

    // 使用 memcpy 复制字符串
    memcpy(dest, src, strlen(src) + 1); // 加 1 是为了复制字符串结尾的空字符

    printf("Source: %s\n", src);
    printf("Destination: %s\n", dest);

    return 0;
}
 

函数实现:

#include<stdio.h>

#include<string.h>

#include<assert.h>

void* my_memcpy(void* dest, const void* sur, size_t num)
{
    void* ret = dest;//记录初始指针位置
    assert(dest && sur);//确保非空
    while (num--)//复制字节的次数
    {
        *(char*)dest = *(char*)sur;//先将void*强制类型转换为1字节大小的char*再逐字节复制;
        dest = (char*)dest + 1;//指针移动一位//void*类型的指针本身不能进行自增自减和解引用操作,所以要强制类型转换;
        sur = (char*)sur + 1;//指针移动一位;
    }
    return ret;返回dest初始指针位置
}

int main()
{
    int a[] = { 1,2,3,4,5 };
    int b[20] = { 0 };
    my_memcpy(b, a, 20);
    for (int i = 0; i < 20; i++)
    {
        printf("%d", b[i]);
    }

 

二:memmove函数及实现 

用于在内存中复制数据块,与 memcpy 类似,但是 memmove 能够正确处理源内存区域和目标内存区域重叠的情况。

void *memmove(void *dest, const void *src, size_t n);
这个函数的功能是从源(src)所指向的内存地址开始复制 n 个字节到目标(dest)所指向的内存地址,即使源和目标内存区域有重叠也能正确复制。memmove 函数会返回目标内存区域的指针。

以下是 memmove 函数的参数说明:

  • dest:指向复制数据的目标内存地址的指针。
  • src:指向要复制的数据源内存地址的指针。
  • n:要复制的字节数。

memmove 函数返回一个指向目标内存区域的指针。

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello World!";
    // 将 "World" 复制到 "Hello" 的位置
    memmove(str + 6, str, 5);

    printf("Resulting string: %s\n", str);
    // 输出应为 "HelloHello!"

    return 0;
}
 

 函数实现:

它有两种办法,一个是先将原字符串拷贝一份,再用这一份进行复制操作,不会造成覆盖的问题,但这样做浪费空间。推荐第二个办法:

 

可以总结得到结论,当des指针在sur之前从前往后复制不会产生覆盖,当des指针在sur之后,从后往前复制,不会产生覆盖。

代码实现:

 

void* my_memmove(void* dest, const void* sur, size_t num)
{
    void* ret = dest;//记录指针初始位置
    assert(dest && sur);//确保指针非空
    if (dest < sur)//dest指针在sur之前时从前往后复制
    {
        while (num--)
        {
            *(char*)dest = *(char*)sur;
            dest = (char*)dest + 1;
            sur = (char*)sur + 1;
        }
    }
    else//dest指针在sur之后,从后往前复制
    {
        while (num--)
        {
            *((char*)dest + num) = *((char*)sur + num);
        }
    }
    return ret;//返回初始指针
}

int main()
{
    int a[] = { 1,2,3,4,5 };
        my_memmove(a + 2, a, 12);
    for (int i = 0; i < 5; i++) {
        printf("%d", a[i]);
    }
}

三:memset函数

 memset 是 C 语言标准库中的一个函数,用于将指定的内存块中的所有字节设置为特定的值。这个函数通常用于初始化结构体、数组或内存缓冲区。

函数原型定义在 <string.h> 头文件中,如下所示:

void *memset(void *s, int c, size_t n);

  • s:指向要设置值的内存块的指针。
  • c:要设置的值。这个值通常是一个整数值,但是因为 memset 是按字节操作的,所以实际上只会使用 c 的最低字节(即 c & 0xFF)。
  • n:要设置的内存块的字节数。

示例:

#include <stdio.h>
#include <string.h>

int main() {
    char str[50] = "This is a string for testing memset function.";

    // 将内存块的前20个字节设置为字符 'X'
    memset(str, 'X', 20);

    printf("Modified string: %s\n", str);
    // 输出应为 "XXXXXXXXXXXXXXXXXXXX for testing memset function."

    return 0;
}
//注意是逐个字节复制,而不是逐元素复制!

 四:memcmp函数

memcmp 是 C 语言标准库中的一个函数,用于比较两个内存区域的前 n 个字节。它逐字节比较两个内存块,并根据比较结果返回一个整数值。

函数原型定义在 <string.h> 头文件中,如下所示:

int memcmp(const void *s1, const void *s2, size_t n);

  • s1:指向第一个内存区域的指针。
  • s2:指向第二个内存区域的指针。
  • n:要比较的字节数。
  • 如果两个内存区域完全相同,返回0。
  • 如果在比较过程中,s1 指向的内存区域中的某个字节大于 s2 指向的内存区域中的对应字节,返回一个正整数。
  • 如果在比较过程中,s1 指向的内存区域中的某个字节小于 s2 指向的内存区域中的对应字节,返回一个负整数。

示例:

#include <stdio.h>
#include <string.h>

int main() {
    const char *str1 = "Hello, World!";
    const char *str2 = "Hello, C World!";
    size_t n = 7; // 比较前7个字符

    int result = memcmp(str1, str2, n);

    if (result == 0) {
        printf("The first %zu bytes of the strings are equal.\n", n);
    } else if (result < 0) {
        printf("The first differing byte in str1 is less than in str2.\n");
    } else {
        printf("The first differing byte in str1 is greater than in str2.\n");
    }

    return 0;
}
 

 在这个例子中,我们比较两个字符串 str1 和 str2 的前7个字符。由于前7个字符在这两个字符串中是相同的,所以 memcmp 将返回0。

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值