前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C语言:内存函数】详解

【C语言:内存函数】详解

作者头像
老九君
发布2022-09-14 20:14:51
1K0
发布2022-09-14 20:14:51
举报
文章被收录于专栏:老九学堂老九学堂

内存函数,即对内存中的内容进行一定的操作,通过这种函数,我们并不会局限与数据的类型。下面大雄就为大家介绍一些常用的内存函数。

01 

【memcpy() - 内存拷贝不重叠】

memcpy()指定头文件是:#include<string.h>

memcpy() 函数的声明方式如下:

代码语言:javascript
复制
void *memcpy(void *str1, const void *str2, size_t n)

参数讲解:

1、str1 → 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

2、str2 → 指向要复制的数据源,类型强制转换为 void* 指针。

3、n → 要被复制的字节数。size_t实际上就是和无符号差不多的。

【注意】它的参数的数据类型是无类型指针,也就是说它所有的数据类型都是可以适用的,因为它是 void * 类型。

返回值讲解:该函数返回一个指向目标存储区 str1 的指针。

这个代码是把arr1的元素赋值给arr2的元素,但是只是赋值前五个元素。可以用memcpy()内存函数来进行实现。

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<string.h>int main(void){  int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  int arr2[10] = { 0 };  memcpy(arr2, arr1, 20);  int i = 0;  for (i = 0; i < 10; i++)  {    printf("%d ", *(arr2 + i));  }}

运行结果:1 2 3 4 5 0 0 0 0 0

创建自定义函数实现memcpy()

【注意】在无类型指针数据类型的时候是不能直接进行解引用操作以及++--的,在这里转换成char*指针类型是最合适的,

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<string.h>#include<assert.h>void *my_memcpy(void *str1, const void *str2, size_t n){  assert(str1 && str2 != NULL);  void *ret = str1;  while (n--)  {    *(char*)str1 = *(char*)str2;    str1 = (char*)str1 + 1;    str2 = (char*)str2 + 1;  }  return ret;}int main(void){  int i;  int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  int arr2[10] = { 0 };  int sz = sizeof(arr1) / sizeof(arr1[0]);  int *ret = my_memcpy(arr2, arr1, 20);  for (i = 0; i < sz; i++)  {    printf("%d ", *(ret + i));  }  return 0;}

运行结果:1 2 3 4 5 0 0 0 0 0

那在这里假设我们想要从arr1当中第三个元素开始进行拷贝怎么办?只需要改变下memcpy()当中第二个参数就可以。

把上述代码的这段修改下即可:

代码语言:javascript
复制
int *ret = my_memcpy(arr2, arr1+2, 20);

只需要这个样子运行,结果就会从第三个元素开始,这里“+2”是下标,是从0开始的注意下这点。 

运行结果:3 4 5 6 7 0 0 0 0 0

【注意】:memcpy函数应该拷贝不重叠的内存。

02 

【memmove() - 内存拷贝可重叠】

memmove()指定头文件是:#include<string.h>

memmove()函数的声明方式如下:

代码语言:javascript
复制
void *memmove(void *str1, const void *str2, size_t n)

参数讲解:

1、str1 → 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。

2、str2 → 指向要复制的数据源,类型强制转换为 void* 指针。

3、n → 要被复制的字节数。该函数返回一个指向目标存储区 str1 的指针。

我们可以发现是和memcpy()一样的

返回值讲解:该函数返回一个指向目标存储区 str1 的指针。

用同一个数组名进行内存拷贝。

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<string.h>int main(void){  int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  memmove(arr1+2, arr1, 20);  int i = 0;  for (i = 0; i < 10; i++)  {    printf("%d ", *(arr1 + i));  }}

运行结果:1 2 1 2 3 4 5 8 9 10

【注意】:在这里如果用memcpy()函数的话是行的,这就是memcpy()函数和memmove()函数的区别所在了。

创建自定义函数实现memmove()

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<string.h>#include<assert.h>void *my_memmove(void *str1, const void *str2, size_t n){    void *ret = str1;    assert(str1 && str2 != NULL);  if (str1 < str2)  {    //前向后,小于。    while (n--)    {      *(char*)str1 = *(char*)str2;      str1 = (char*)str1 + 1;      str2 = (char*)str2 + 1;    }  }  else  {    //后向前,大于。    while (n--)    {      *((char*)str1 + n) = *((char*)str2 + n);    }  }  return ret;}int main(void){  int i = 0;  int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  //               1  2  1  2  3  4  5  8  9  10  my_memmove(arr1+2, arr1, 20);  return 0;}

str1 > str2运行结果:

1 2 1 2 3 4 5 8 9 10

再来看看str2<str1的调试结果,把上述代码的这段修改下即可:

代码语言:javascript
复制
my_memmove(arr1, arr1+2, 20);

str2<str1运行结果:

3 4 5 6 7 6 7 8 9 10

03 

【memcmp() - 内存比较】

memcmp() 指定头文件是:#include<string.h>

memcmp() 函数的声明方式如下:

代码语言:javascript
复制
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

参数讲解:

1、ptr1 → 指向内存块的指针。

2、str2 → 指向内存块的指针。

3、n → 要被比较的字节。

返回值讲解:

1、返回值 < 0,表示 ptr1 小于 ptr2。

2、返回值 > 0,表示 ptr1 大于 ptr2。

3、返回值 = 0,表示 ptr1 等于 ptr2。

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include <string.h>int main(void){  char str1[15] = {0};  char str2[15] = {0};  int ret = 0;   memcpy(str1, "ABCDEF", 6);  memcpy(str2, "ABCDEF", 6);   ret = memcmp(str1, str2, 1);   if (ret > 0)  {    printf("str2 小于 str1");  }  else if (ret < 0)  {    printf("str1 小于 str2");  }  else  {    printf("str1 等于 str2");  }  return 0;}

运行结果:str1 等于 str2

【注意】两组数组名是相同的,所对应的ASCII码值。

memcmp()源程序

代码示例:

代码语言:javascript
复制
int __cdecl memcmp (        const void * buf1,        const void * buf2,        size_t count        ){        if (!count)                return(0); #if defined (_M_X64)    {        __declspec(dllimport)         size_t RtlCompareMemory( const void * src1, const void * src2, size_t length );         size_t length;         if ( ( length = RtlCompareMemory( buf1, buf2, count ) ) == count ) {            return(0);        }         buf1 = (char *)buf1 + length;        buf2 = (char *)buf2 + length;    } #else  /* defined (_M_X64) */         while ( --count && *(char *)buf1 == *(char *)buf2 ) {                buf1 = (char *)buf1 + 1;                buf2 = (char *)buf2 + 1;        } #endif  /* defined (_M_X64) */         return( *((unsigned char *)buf1) - *((unsigned char *)buf2) );}

04 

【memset() - 内存填充块】

memset() 指定头文件是:#include<string.h>

memset() 函数的声明方式如下:

代码语言:javascript
复制
void * memset ( void * ptr, int value, size_t num );

参数讲解:

1、ptr→指向要填充的内存块的指针。

2、value→要设置的值。该值作为int类型传递,但该函数使用该值的unsigned char转换填充内存块。实际上就是我们所要初始化的内容。

3、num→要设置为该值的字节数。Size_t是一个无符号整型类型。

返回值讲解:返回ptr。

代码示例:

代码语言:javascript
复制
#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include <string.h> int main(){  char str[] = " yysyyyds!";  memset(str, 'C', 1);  puts(str);  return 0;}

运行结果:Cyysyyyds 

memset()源程序

代码示例:

代码语言:javascript
复制
void * __cdecl memset (        void *dst,        int val,        size_t count        ){        void *start = dst; #if defined (_M_X64)         {          __declspec(dllimport)          void RtlFillMemory( void *, size_t count, char );         RtlFillMemory( dst, count, (char)val );         } #else  /* defined (_M_X64) */        while (count--) {                *(char *)dst = (char)val;                dst = (char *)dst + 1;        }#endif  /* defined (_M_X64) */         return(start);}

活动

热门

等等!还没完,新月份新气象

针对各位卷王

我们更新升级了两门专属课程

帮你开拓编程之路

限时“骨折”优惠中……

快来薅羊毛吧!

静香QQ:1705214200了解详情

阅读原文

了解老九学堂线下高薪就业班详情

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老九学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档