C语言常用的内存操作函数

在C语言中经常会操作内存中的数据,下面来介绍一下常用的一些内存操作函数。

memcpy

memcpy用于从source的位置开始向后复制num个字节到destination的内存位置,其函数原型如下:

cpp 复制代码
//destination是目标地址,source是源地址,num是要复制的字节数,返回的是目标地址。因为不知道内存中存储的是什么数据类型,所以都用void*
void * memcpy ( void * destination, const void * source, size_t num );

下面举一个应用的例子:

cpp 复制代码
#include <stdio.h>
#include <string.h>
struct
{
    char name[40];
    int age;
} person, person_copy;
int main()
{
    char myname[] = "Pierre de Fermat";
    /* using memcpy to copy string: */
    memcpy(person.name, myname, sizeof(myname));
    person.age = 46;
    /* using memcpy to copy structure: */
    memcpy(&person_copy, &person, sizeof(person));
    printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
    return 0;
}

需要注意的是,C标准规定使用memcpy拷贝的目标地址和源地址空间不能出现重叠 ,否则会出错(vs编译器对memcpy进行了优化,使其空间可以重叠):

cpp 复制代码
int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8};
//这里是想把12345拷贝到34567的位置,预期结果是12123458,按照C语言标准,如果使用memcpy当把12拷贝到34位置后,继续应该把34拷贝到56的位置,而此时34已经变成了12,所以还会把12拷贝到56,然后把5拷贝到7,此时5已经变成了1,所以最后会得到12121218
    memmove(arr + 2, arr, 5 * sizeof(int));
    for (int i = 0; i < 8; i++)
    {
        printf("%d ", arr[i]);//这里可以正常打印出12123458,是因为vs编译器进行了优化
    }
    return 0;
}

下面来模拟实现一下memcpy函数:

cpp 复制代码
/*
 * @brief    内存拷贝函数,将src地址开始的num个字节的数据拷贝到dest
 * @param    dest:目标地址
 * @param    src:源地址
 * @param    num:拷贝的字节数
 * @return   void*: 返回dest
 */
void *my_memcpy(void *dest, const void *src, size_t num)
{
    assert(dest && src);//防止传入空指针
    void *temp = dest;//用于返回
    while (num--)//循环num次,每次拷贝一个字节
    {
        *(char *)dest = *(char *)src;//先把两个地址强转成char*,每次操作一个字节
        dest = (char *)dest + 1;//操作完一次后地址++
        src = (char *)src + 1;
    }
    return temp;//返回目标地址
}

memmove

memmove就是在memcpy的基础上增加了处理重叠内存的功能,其函数原型如下:

cpp 复制代码
//destination是目标地址,source是源地址,num是要复制的字节数,返回的是目标地址。因为不知道内存中存储的是什么数据类型,所以都用void*
void * memmove ( void * destination, const void * source, size_t num );

所以当destination小于source时,应该从前向后 拷贝, destination大于source时,应该从后向前拷贝,下面来模拟实现一下memmove:

cpp 复制代码
/*
 * @brief    内存移动,源和目标地址重叠时的memcpy
 * @param    dest:目标地址
 * @param    src:源地址
 * @param    num:要拷贝的字节数
 * @return   void*:返回目标地址
 */
void *my_memmove(void *dest, void *src, size_t num)
{
    assert(dest && src);
    void *temp = dest;
    if (dest < src) // 前->后
    {
        while (num--)
        {
            *(char *)dest = *(char *)src;
            dest = (char *)dest + 1;
            src = (char *)src + 1;
        }
    }
    else
    {
        while (num--) // 后->前
        {
            *((char *)dest + num) = *((char *)src + num);
        }
    }
    return temp;
}

memcmp

memcmp用于比较两个内存中的内容是否相等,类似于strcmp,其函数原型如下:

cpp 复制代码
//ptr1是第一块内存的起始地址,ptr2是第二块内存起始地址,num是要比较的字节数,如果第一块内存内容大于第二块,返回正数,反之返回负数,相等返回0
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

memset

memset用于设置指定内存中的数据,其函数原型如下:

cpp 复制代码
//ptr是要设置的内存起始地址,value是要设置的值,num是要设置的字节数,返回ptr
void* memset(void* ptr, int value, size_t num);

下面举一些应用例子:

cpp 复制代码
int main()
{
    char arr[] = "hello world";
    int arr1[5] = {1,2,3,4,5};
    memset(arr,'x',5*sizeof(char));
    printf("%s\n",arr);//会打印xxxxx world,把前5个字节替换成了x
    memset(arr1,0,5*sizeof(int));
    for(int i = 0; i < 5; i++)
    {
        printf("%d ",arr1[i]);//会打印00000,将5个int型,也就是20个字节换成了0
    }
    memset(arr1,1,5*sizeof(int));
//会打印16843009 16843009 16843009 16843009 16843009,是将每个字节都换成了1,一个int有四个字节,所以如果想将一个int数组的每个元素设置成0以外的数,不能用memset
    for(int i = 0; i < 5; i++)
    {
        printf("%d ",arr1[i]);
    }
}
相关推荐
Scott9999HH17 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社18 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海18 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖19 小时前
JDK 26 新特性详解
java·开发语言
马优晨20 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区1 天前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大1 天前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai1 天前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜1 天前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa1 天前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio