1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 【C语言】memcpy memmove memset memcmp 四大内存操作函数(详解+用法+模拟实现)

【C语言】memcpy memmove memset memcmp 四大内存操作函数(详解+用法+模拟实现)

时间:2023-02-24 13:46:29

相关推荐

【C语言】memcpy memmove memset memcmp 四大内存操作函数(详解+用法+模拟实现)

头文件<string.h>中常用内存操作函数共有四大,学习完本篇文章,各种类型数组的常见处理轻松拿下。

文章目录

零、前言一、memcpy 内存拷贝函数my_memcpy 二、memmove 内存移动函数my_memmove 三、memset 内存赋值函数my_memset 四、memcmp 内存比较函数my_memcmp

零、前言

对字符串(字符数组)的操作函数有很多,但是我们想要操作整型数组等呢:

这就需要内存操作函数了,memory在计算机科学中是内存的意思,这也是四大内存操作函数都有mem头的原因。

与void*类型指针重要的知识:

void*类型指针可以指向任何类型的数据,但是void*类型指针无法访问地址数据。这是因为指针压根就不知道它要访问多大空间,那么即使能访问得到的数据也毫无意义。因此不能对void*类型指针解引用操作,也不能做地址偏移±操作,这是语法型错误。

本文提及的字符串相关函数不熟悉的可以查看文章【C语言】<string.h>中十大字符串函数(用法+模拟实现)。

一、memcpy 内存拷贝函数

我们知道strcpy(字符串拷贝函数)可以将一个字符串内容拷贝到另一个字符串,如果我们想拷贝整型数组,我们可以使用memcpy内存拷贝函数。

memcpy头文件:string.h

memcpy功能:逐字节地拷贝num个字节内存,并会覆盖原来内容。

memcpy函数声明:

void * memcpy ( void * dst, const void * src, size_t num );

src(source)源内存首字节地址,dst(destination)目标内存首字节地址。

num是需要拷贝的字节数。

memcpy返回的是dst首字节地址,并且是void*型,接收返回值需要强制类型转换。

memcpy使用实例:

#include <stdio.h>#include <string.h>int main(){int arr1[10] = {0 };int arr2[10] = {1,2,3,4,5,6,7,8,9,10 };memcpy(arr1, arr2, 4 * sizeof(arr2[0]));for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);printf("\n");memcpy(arr1+2,arr1,4*sizeof(arr1[0]));//理想拷贝后效果应该是1 2 1 2 3 4 0 0 0 0//实际输出是1 2 1 2 1 2 0 0 0 0 因为原来的3 4被提前覆盖了for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);return 0;}

注意:

dst和src都要有超过num个字节的空间。

源内存块src和目标内存块dst有任何的重叠,复制的结果都是未定义的。

my_memcpy

void *my_memcpy(void *dst, const void *src, int num){//将void*型强制转化成char*,能够逐字节访问char *tmp_dst = (char *)dst;const char *tmp_src = (const char *)src;//循环num次,拷贝num个字节for (int i = 0; i < num; i++){*tmp_dst++ = *tmp_src++;}return dst;}

二、memmove 内存移动函数

memmove和memcpy的差别就是处理的源内存块和目标内存块是可以重叠的。

memmove头文件:string.h

memmove功能:将源内存块num个字节移动到目标内存块,源内存块内容并不消失。

memmove函数声明:

void * memmove ( void * dst, const void * src, size_t num );

src(source)源内存首字节地址,dst(destination)目标内存首字节地址。

num是需要拷贝的字节数。

memmove返回的是dst首字节地址,并且是void*型,接收返回值需要强制类型转换。

memmove使用实例:

#include <stdio.h>#include <string.h>int main(){int arr1[10] = {0 };int arr2[10] = {1,2,3,4,5,6,7,8,9,10 };memmove(arr1, arr2, 4 * sizeof(arr2[0]));printf("arr1:");for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);printf("\narr2:");for (int i = 0; i < 10; i++)printf("%d ", arr2[i]);//理想拷贝后效果应该是1 2 1 2 3 4 0 0 0 0printf("\narr1自己移动自己:");memmove(arr1 + 2, arr1, 4 * sizeof(arr1[0]));for (int i = 0; i < 10; i++)printf("%d ", arr1[i]);return 0;}

注意:dst和src都要有超过num个字节的空间。

my_memmove

memmove的模拟关键在于解决内存块重复部分移动问题。

首先要比较dst和src两个地址大小,原因如下:

如果要将1 2 3 4 5 6 7 8的src 1 2 3 4移动到dst 3 4 5 6位置,就要从4开始倒着移动,才能避免重叠部分移动错误。如果要将src 3 4 5 6移动到dst 1 2 3 4位置,就要从3开始正着移动。如果不是重叠内存块拷贝,正着倒着移动都一样,地址位置判断并不影响。

void *my_memmove(void *dst, const void *src, int num){char *tmp_dst = (char *)dst;const char *tmp_src = (const char *)src;if (src > dst)for (int i = 0; i < num; i++)*tmp_dst++ = *tmp_src++;elsefor (int i = num-1; i >=0; i--)*(tmp_dst + i) = *(tmp_src + i);return dst;}

三、memset 内存赋值函数

memset头文件:string.h

memset功能:给一片内存num个字节赋上指定值

memset函数声明:

void * memset ( void * ptr, int value, size_t num );

ptr是内存块首字节地址。

value是要赋的值,这个值应该不超过一个无符号字节大小即28-1

num是需要赋值的字节数。

memset返回值是ptr首字节地址,并且是void*型,接收返回值需要强制类型转换。

memset使用实例:

#include <stdio.h>#include <string.h>int main(){char carr[10] = {0 };memset(carr, 65, sizeof(carr));printf("字符型:");for (int i = 0; i < 10; i++)printf("%c ",carr[i]);int darr[4] = {0 };printf("\n整型:");memset(darr, 1,sizeof(darr));for (int i = 0; i < 4; i++)printf("%d ", darr[i]);return 0;}

注意:

内存块要有num个字节大小。

给每个字节赋值,比如int型是4字节,赋值1,输出是16843009而不是1。

my_memset

void *my_memset(void *ptr, int value, int num){//强制类型转换为无符号char*型unsigned char *tmp_ptr = (unsigned char *)ptr;//循环num次for (int i = 0; i < num; i++){//因为char是特殊的整型,所以可以直接赋值*tmp_ptr++ = value;}return ptr;}

四、memcmp 内存比较函数

memcmp头文件:string.h

memcmp功能:逐字节地比较从ptr1和ptr2开始的num个字节,直至比出。

memcmp函数声明:

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

ptr1是一个内存块首字节地址,ptr2是另一个内存块首字节地址。

num是需要比较的字节数。

ptr1>ptr2返回值>0,ptr1<ptr2返回值<0,完全相等返回值0。

memcmp使用实例:

#include <stdio.h>#include <string.h>int main(){int arr1[10] = {1,2,3,4,5,6,7,8,9,10 };int arr2[10] = {1,2,3,4,5,7,7,7,7,7 };if (memcmp(arr1, arr2, sizeof(arr1)) > 0)printf("arr1大");else if (memcmp(arr1, arr2, sizeof(arr1)) < 0)printf("arr2大");elseprintf("arr1和arr2一样大");return 0;}

注意:内存块要有num个字节大小。

my_memcmp

int my_memcmp(const void *ptr1, const void *ptr2, int num){//先强制类型转换const char *tmp_ptr1 = (const char *)ptr1;const char *tmp_ptr2 = (const char *)ptr2;//循环num次,比较出就返回值for (int i = 0; i < num; i++){if (*(tmp_ptr1+i) > *(tmp_ptr2+i))return 1;else if (*(tmp_ptr1+i) < *(tmp_ptr2+i))return -1;}//比较完num个字节了,仍没返回,完全相等返回值0。return 0;}

熟练掌握库函数,敲码速度倍倍翻。

码字不容易,欢迎关注、点赞、收藏、评论、转发。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。