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]);
    }
}
相关推荐
ChoSeitaku15 分钟前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
娅娅梨17 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
DdddJMs__13520 分钟前
C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
c语言·leetcode·题解
汤米粥22 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾25 分钟前
EasyExcel使用
java·开发语言·excel
拾荒的小海螺31 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
娃娃丢没有坏心思1 小时前
C++20 概念与约束(2)—— 初识概念与约束
c语言·c++·现代c++
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法