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

2022-09-14 20:14:51 浏览数 (1)

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

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了解详情

阅读原文

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

0 人点赞