首页 > 系统相关 >c语言——内存函数

c语言——内存函数

时间:2024-11-14 22:46:57浏览次数:3  
标签:src 语言 int char dest 内存 字节 include 函数

1.memcpy函数使用和模拟

2.memmove函数使用和模拟

3.memset函数使用

4.memcmp函数使用

上一篇博客我给大家一 一介绍了字符串相关的函数,那么这一篇我想给大家介绍关于内存方面的函数,内存函数,他是不考虑类型的,他只考虑从内存进行处理的一系列函数

1.memcpy函数

memcpy是用来拷贝内存信息的内存函数,它可以拷贝我们想要的信息,但是要注意,他是通过字节的大小进行拷贝的,而不是元素个数

memcpy函数是用来拷贝不相关的内存数据,可以是任意类型的数据

但是如果是同一个内存同一个空间拷贝,那么拷贝就会出错

而strcpy只能拷贝字符串

#include<stdio.h>
#include<string.h>
int main()
{
  int arr1[10]={1,2,3,4,5,6,7,8,9,10};
  int arr2[10]={0};
  memcpy(arr2,arr1,5*sizeof(int));
//arr2是destination,arr1是source,将源头拷贝到目标地址
//并且只拷贝5*sizeof(int)个字节,即20个字节,即5个元素
  int i = 0;
  for(i=0;i<10;i++)
   {
      printf("%d ",arr2[i]);
   }
  return 0;
}

当我们会使用memcpy这个函数时,那让我们来模拟实现一下吧!!!

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest,void* src,size_t num)
{
   char* r = dest;//接收dest的起始地址,为了方便我们最后return dest的起始地址
   assert(dest && src!=NULL);
   while(num--)
   {
      *(char*)dest = *(char*)src;//因为memcpy是void*,他并不知道我们要传递多少个字节
     //如果以后我们要传递7个字节的char类型,但是我们强制类型转换为int,那么int一次会跳过4个字 
     //节,所以我们使用char*,一次访问一个字节,就可以避免以后跳过字节不匹配
     
     dest = (char*)dest + 1;//所以这里我们也把dest和src每次前进一个char*字节
     src = (char*)src + 1;   //每次一个字节一个字节交换
   }

    return r;
}


int main()
{
  int arr1[10]={1,2,3,4,5,6,7,8,9,10};
  int arr2[10]={0};
  my_memcpy(arr2,arr1,5*sizeof(int));
  int i=0;
  for(i=0;i<10;i++)
  {
     printf("%d ",arr2[i]);
  }

  return 0;
}

2.memmove函数

他的使用方法和memcpy相同

不同的是memmove可以拷贝重叠的内容,即同一个地址的内容

#include<stdio.h>
#include<string.h>
int main()
{
  int arr[10]={1,2,3,4,5,6,7,8,9,10};
  memmove(arr+5,arr+3,5*sizeof(int));
//将arr+3后面的5*sizeof(int)个字节的元素,拷贝到第arr+5后面的元素中
//这就是memmove特别的地方
  int i = 0;
  for(i=0;i<10;i++)
   {
      printf("%d ",arr[i]);
   }


  return 0;
}

当我们知道如何使用memmove时,让我们来尝试模拟实现一下吧!!

#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest,void* src,size_t num)
{
   void* r = dest;//记住dest起始地址,方便return dest的起始地址打印
   assert(dest && src !=NULL);
   //这里拷贝重叠内容会有俩种情况
   //第一种:dest的起始地址大小于src的起始地址,说明dest再src前面
   //所以要从前-->往后拷贝
     if(dest < src)
     {
        while(num--)
        {
            *(char*)dest = *(char*)src;
             dest = (char*)dest + 1;
             src = (char*)src + 1;
         }
     }
      //第二种情况:当dest的起始地址大于src
      //说明dest再src后面,所以要从后-->往前拷贝
     else
     { 
        while(num--)
         {
             //num进来时候,num=19,就可以让dets和src跑到最后一个字节,从后向前一个字节一个 
              //字节拷贝
           *((char*)dest + num) = *((char*)src + num);
         }
     }
       return r;
}


int main()
{
   int arr[10]={1,2,3,4,5,6,7,8,9,10};
   my_memmove(arr+5,arr+3,5*sizeof(int));
   int i = 0;
   for(i=0 ; i<10 ; i++)
    {
       printf("%d ",arr[i]);
    }

   return 0;
}

再模拟实现memmove时候,我们要多考虑一步,dest是再src的前面呢?还是在src后面呢?

如果再src前面,那么从前-->向后拷贝

如果再src后面,那么从后-->向前拷贝

多考虑这一步是为了避免我们拷贝的内容拷贝重复

3.memset的使用

memset可以设置我们想要更换元素的多少字节

注意:这里更换的是字节!!!不是元素个数!!

#include<stdio.h>
#include<string.h>
int main()
{
   char arr[10]={0};
   memset(arr,'k',6*sizeof(char));
//在arr数组中,我要更换6*sizeof(char)个字节的字符k
//这里要通过调试观察

   return 0;
}

#include<stdio.h>
#include<string.h>
int main()
{
   int arr[10]={0};
   memset(arr,1,5*sizeof(int));
//在arr数组中,将5*sizeof(int)个字节设置为1
//在调试中观察
   return 0;
}

4.memcmp的使用

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,9};
   int r1 = memcmp(arr1,arr2,3*sizeof(int));
//第一个memcmp比较的是arr1和arr2中前3*sizeof(int)个字节的大小,即前3个元素的大小
//如果arr1大于arr2,那么返回>0,如果相等,则返回0,小于,则返回<0
   printf("%d\n",r1);

   int r2 = memcmp(arr1,arr2,4*sizeof(int));
//这里是比较arr1和arr2中前4*sizeof(int)个字节的大小,即前4个元素的大小
/如果arr1大于arr2,则返回>0,相等则返回0,小于则返回<0
   printf("%d\n",r2);

   return 0;
}

标签:src,语言,int,char,dest,内存,字节,include,函数
From: https://blog.csdn.net/CJH20050707/article/details/143781558

相关文章

  • 析构函数
    与构造函数相对应,构造函数是对象创建的时候自动调用的,而析构函数就是对象在销毁的时候自动调用的。与构造函数作用刚好相反,构造函数是用来初始化成员变量,析构函数是用来释放对象占用的资源。A(constintdata){cout<<"A的构造函数"<<endl;m_data=newint(data);*m_data......
  • 构造函数C++
    1.构造函数的介绍功能:专门用于对象的初始化工作,在类的对象创建时定义初始状态特点构造函数的名字和类名是相同的构造函数是没有返回值类型的,也不能写void。可以有形参(也可以重载)在创建对象的时候,会自动调用。而且是一定会调用,但是只会调用一次,不能通过已有......
  • 【java开发】什么是内存溢出和内存泄漏?如何解决?
    一、内存溢出1.1导致的原因1.2解决方法二、内存泄漏2.1导致的原因2.2解决方法2.3示例代码三、对比四、总结内存溢出和内存泄漏是我们经常听到的两种内存管理问题,那么,它们是如何导致的?又该如何解决?这篇文章,我们来聊一聊。一、内存溢出内存溢出(O......
  • 初识JVM,JVM自动内存管理
    文章目录一、前言1.1计算机==>操作系统==>JVM1.1.1虚拟与实体(对上图的结构层次分析)1.1.2Java程序执行(对上图的箭头流程分析)二、JVM内存空间与参数设置2.1运行时数据区2.2关于StackOverflowError和OutOfMemoryError2.2.1StackOverflowError2.2.2OutOfMemoryErr......
  • 深入浅出C#编程语言
    引言随着.NET框架的发展,C#(发音为“CSharp”)已经成为一种非常流行且功能强大的面向对象和类型安全的编程语言。自2002年由微软首次发布以来,C#已经经历了多个版本的迭代,每个新版本都带来了更多的特性和改进。本文旨在为初学者提供一个C#编程语言的基础概述,并探讨其一些核心......
  • 探索Google Earth Engine:利用MODIS数据和R语言进行2000-2021年遥感生态指数(RSEI)的时空
    前段时间,小编学习了在GEE上进行遥感生态指数(RSEI)的评估,非常头疼,但是实验了两周后,亲测有效,主要采用的是MODIS数据分析了2000-2021年中国内蒙古某地的RSEI时间序列分布状况,现在把学习的代码分享给大家。1GEE计算RSEI1.1研究区域导入与初步定义varsa=ee.FeatureCollection(......
  • C语言双相循环链表增删查改(带头节点)
    C语言双相循环链表增删查改(带头节点)最后一个节点的next指针指向第一个节点,第一个节点的prev指针指向最后一个节点定义链表节点#include<stdio.h>#include<stdlib.h>//内存管理,malloc(size_tsize)//链表节点结构体typedefstructNode{intdata;s......
  • C语言:数组(一维数组,二维数组,数组越界,数组作为函数参量,冒泡排序)
    1、一维数组的创建和初始化1.1、数组的创建数组是相同类型元素的集合•数组中可以存放1个或者多个数据•数组中存放的数据,类型是相同的数组的创建方式:元素类型自定义数组名(常量表达式)比如:intarr[10]doublearr[5]chararr[8+5]错误写法:intarr[n];......
  • C语言中的函数(大白话理解,超详细)
    1、函数是什么?函数就是一种工具,你需要的时候就可以调用他,简化写代码的工作量每个C语言程序至少有一个函数,即主函数main()2、C语言中函数的分类2.1、库函数库函数:是预先编写好的、可供程序员直接使用的函数注意:1、使用库函数必须包括#include对应的头文件(就是""或<>里......
  • 2- R语言基本图形绘制之直方图——基于ggplot2
      直方图通过在x轴上将值域分割为一定数量的数据桶,在y轴上显示相应值的频数,展示了连续型变量的分布。  ggplot(data,aes(x=contvar))+geom_histogram()  #data是一个数据框;contvar是一个连续型变量。  下面我们使用ggplot包中的mpg数据框,分析2008年117个汽......