C语言部分内存操作函数详解+模拟实现

目录

          1、memcpy函数

          2、memmove函数

          3、memset函数

          4、memcmp函数       

注:1、本文中所提到的4个内存操作函数的头文件均为<string.h>

       2、本文中所用例子均为本人在VS2022 Debug X86的环境下测试所得

一、memcpy函数

1、函数中最前面的void*代表着该函数的返回类型可以为一个任意类型的指针。

2、该函数的作用就是从source的内存位置开始向后复制num个字节的数据到destination的内存位置。

3、该函数在复制的过程中即使遇到'\0'也不会停下,而是会继续复制,直到num个字节复制完。

注意:

(1)destination的空间要足够大 或者说 所要复制内容的大小不能超过destination的大小,否则程序会崩溃。

ex:

(2)如果所设置复制的字节数(num)超过source本身的大小,则后面会复制随机值,直到num个字节。

ex:

4、如果source和destination有任何的重叠,复制的结果都是未定义的

注:其实,C语言标准只是规定memcpy来实现不重叠的内存拷贝,但实际上发现在VS2022这个环境中的memcpy即使面对内存重叠的拷贝,它一样能够拷贝好,即VS2022中的memcpy能够超额完成任务。

ex:

memcpy函数模拟实现

#include<stdio.h>
#include<assert.h>
void * my_memcpy(void* dest,const void* source,size_t num)
{
    assert(dest&&source);//断言一下,避免传过来的是NULL(空指针),因为后面要解引用这两个指针
    void* ret=dest;
    while(num--)
    {
        *(char*)dest=*(char*)source;
        dest=(char*)dest+1;
        //注意:这里不能写成(char*)dest++;--因为强制类型转换(类型)都是临时的,当后置++的时候dest又已经变回原本的类型了
        //     即使这里改成++(char*)dest;--这样改有时候可以,有时候不行,效果不好
        source=(char*)source+1;
    }
    return ret;
}
int main()
{
    int arr1[10]={0};
    int arr2[]={1,2,3,4,5};
    my_memcpy(arr1,arr2,sizeof(arr2));
    int i=0;
    for(i=0;i<10;i++)
    {
        printf("%d ",arr1[i]);
    }
    return 0;
}

二、memmove函数

1、函数中最前面的void*代表着该函数的返回类型可以为一个任意类型的指针。

2、该函数的功能和使用时的注意事项与memcpy类似,这里就不多重复了,唯一的差别就是memmove函数处理的源内存块和目标存块是可以重叠的,即如果源空间和目标空间出现重叠,就使用memmove函数处理。

注:memmove函数通俗一点讲它就是memcpy函数的升级版,源空间与目标空间无论重不重叠都可以使用该函数进行内存中数据的拷贝。

memmove函数模拟实现

#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest,const void* src,size_t num)
{
    assert(dest&&src);//断言一下,避免传过来的是NULL(空指针),因为后面要解引用这两个指针,但空指针是不能被解引用访问的
    void* ret=dest;
    if(src<dest)//src<dest,就从后向前拷贝,ex:先把5拷贝到7,再把4拷贝到6,以此类推...
    {
        while(num--)
        {
            *((char*)dest+num)=*((char*)src+num);
        }
    }
    if(src>dest)//src>dest,就从前向后拷贝,ex:先把3拷贝到1,再把4拷贝到2,以此类推...
    {
        while(num--)
        {
            *(char*)dest=*(char*)src;
            dest=(char*)dest+1;
            src=(char*)src+1;
        }
    }
    return ret;
}
int main()
{
    int arr[]={1,2,3,4,5,6,7,8,9,10};
    my_memmove(arr+2,arr,20);
    int i=0;
    for(i=0;i<10;i++)
    {
        printf("%d ",arr[i]);
    }
    return 0;
}

三、memset函数

1、函数中最前面的void*代表着该函数的返回类型可以为一个任意类型的指针。

2、以字节为单位进行内存的设置的。

3、该函数的作用是设置内存的,将从ptr开始往后的num个字节的数据设置成value。

ex:

注意:

设置的时候要注意,设置的字节数不能超出ptr所指的范围了,否则程序会崩溃。

ex:

memset函数模拟实现

#include<stdio.h>
#include<assert.h>
void* my_memset(void* ptr, int value, size_t num)
{
	assert(ptr);
	void* ret = ptr;
	while (num--)
	{
		*(char*)ptr = (char)value;
		ptr = (char*)ptr + 1;
	}
	return ret;
}
int main()
{
	char arr[] = "hello world";
	my_memset(arr + 6, 'x', 3);
	printf("%s\n", arr);
	return 0;
}

四、memcmp函数

1、该函数的功能为比较ptr1和ptr2指针的前num个字节的内容。

2、比较规则:

如果ptr1<ptr2,则返回<0的数字。

如果ptr1==ptr2,则返回数字0。

如果ptr1>ptr2,则返回>0的数字。

注意:是以字节为单位来比较的。

ex:

通过调试打开内存窗口观察可以发现(一行代表4个字节,00两个数字为一个字节,因为这是以十六进制的形式表示的且VS2022数据采用的是小端存储模式)

arr1和arr2的前13个字节的内容是完全一样的,所以打印的结果为0。

memcmp函数模拟实现

#include<stdio.h>
#include<assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);
	while (num--)
	{
		if (*(char*)ptr1 != *(char*)ptr2)
		{
			return *(char*)ptr1 - *(char*)ptr2;
		}
		ptr1 = (char*)ptr1 + 1;
		ptr2 = (char*)ptr2 + 1;
	}
	return 0;
}
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,0x11223304 };
	printf("%d\n", my_memcmp(arr1, arr2, 13));
	int arr3[] = { 1,2,3,5 };
	printf("%d\n", my_memcmp(arr2, arr3, 13));
	int arr4[] = { 1,2,3,3 };
	printf("%d\n", my_memcmp(arr2, arr4, 13));
	return 0;
}

文章到这就结束了,本人也只是一个刚接触编程两三个月的新手,如果本文中有什么不足之处,希望您能在留言区留言指点,有什么问题也可以在留言区留言,谢谢。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值