Mymemcpy

本文介绍了一个名为Mymemcpy的函数实现细节,该函数用于高效地进行内存拷贝,特别关注了不同位数的操作系统中数据类型的字节大小,并讨论了如何处理内存重叠的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     Mymemcpy这个函数实现了数组、字符串等等的内存拷贝,解决了内存重叠、拷贝速度的问题,这里值得注意的是为了实现拷贝速率的提升,要考虑字节对齐问题,这样想,如果考虑操作系统字长对齐(应用程序相对于操作系统), 那么在32位操作系统上,可以4个字节4个字节地考虑,在64位操作系统上,可以8个字节8个字节地拷贝。

      在这里补充一点额外的思考成果:在32位系统时,它的寻址恰好是4个字节,而在64位操作系统上,它的寻址是8个字节。在这里要注意,int 类型在16位操作系统是16位,也就是两个字节,在32位操作系统下是32位,也就是4个字节,在64位操作系统为什么int还是4个字节呢?这是因为人们已经习惯了。

(1)16位平台   


char         1个字节8位  


short        2个字节16位  


int             2个字节16位  


long         4个字节32位  


指针         2个字节16位   


(2)32位平台   


char         1个字节8位  


short        2个字节16位  


int             4个字节32位  


long         4个字节32位 


long long    8个字节64位   


指针         4个字节32位   


(3)64位平台   


char     1个字节  


short     2个字节 


 int                 4个字节   


long             8个字节(区别)  


long long    8个字节   


指针             8个字节(区别) 


     在此留点疑惑:cache   还有小内存拷贝方案,大内存拷贝方案。


#include<stdio.h>

#include<stdlib.h>
#include<assert.h>
#include<string.h>


void *Mymemcpy(void *dest, const void *src, int count)


{


    void *ptr = dest;

    /*char *p1 = (char *)dest;
char *p2 = (char *)src;*/
int count1 = count/sizeof(dest);//int *
int count2 = count%sizeof(dest);//char *
//printf("%d %d\n",count1,count2);
if(count1>0)
{
int *p1 = (int *)dest;
int *p2 = (int *)src;



if(dest>src && count<p1-p2)//如果源在目标之前(dest>src)并且所要拷的字节数小于两指针的间距
{
while(count1>0)
{
    *p1++ = *p2++;

    count1--;  
}
p1--;
}
else//内存重叠问题,如果源在目标之前并且所要拷的字节数大于两指针的间距;如果源在目标之后,则不存在内存重叠问题(++拷贝)
{
int *p3 = (int *)dest+count/sizeof(dest)-1;
    int *p4 = (int *)src+count/sizeof(dest)-1;
while(count1>0)
{
*p3-- = *p4--;
  count1--;
}
p3++;
}
}


if(count2>0)
{
char *p1 = (char *)dest;
char *p2 = (char *)src;



if(dest>src && count<p1-p2)//不重叠
{
while(count2>0)
{
    *p1++ = *p2++;

    count2--;
}
p1--;
}
else//内存重叠问题
{
p1 = (char *)dest+count-1;
    p2 = (char *)src+count-1;
while(count2>0)
{
*p1-- = *p2--;
count2--;
}
p1++;
}
}


return ptr;


}


int main()
{

char src[] = "abcdefgh";
char des[] = "111111";
char src1[] = "abcde";

char des1[] = "111111";

char src2[] = "abcdefgh";

int arr[] = {1,2,3,4,5,6,7,8,9};
int brr[] = {1,2,3,4};
int crr[] = {4,4,4,4,4,4};

printf("%s\n",Mymemcpy(&src[0],&src[3],2*sizeof(char)));//源在目标之后

printf("%s\n",Mymemcpy(&src2[3],&src2[0],4*sizeof(char)));//源在目标之前

Mymemcpy(&arr[0],&arr[3],2*sizeof(int));
Mymemcpy(crr,brr,2*sizeof(int));
int i = 0;
for(i = 0;i<9;i++)
{
      printf("%d ",arr[i]);
}
printf("\n");
printf("%s\n",Mymemcpy(des1,src1,1*sizeof(char)));
for(i = 0;i<6;i++)
{
printf("%d ",crr[i]);
}
printf("\n");

return 0;
}
#ifndef __MALLOC_H #define __MALLOC_H #include "stm32f10x.h" // 内存池定义:STM32F103C8T6只有内部RAM(20KB),不包含外部RAM #define SRAMIN 0 // 内部内存池编号 #define SRAMBANK 1 // 内存池数量(仅使用1个) // 内存管理参数调整(适配C8T6的20KB RAM) #define MEM1_BLOCK_SIZE 32 // 内存块大小设为32字节(提高小内存分配效率) #define MEM1_MAX_SIZE 12 * 1024 // 分配给内存管理的最大内存(12KB,保留8KB给堆栈和系统) #define MEM1_ALLOC_TABLE_SIZE (MEM1_MAX_SIZE/MEM1_BLOCK_SIZE) // 管理表大小 // 内存管理设备结构体 struct _m_mallco_dev { void (*init)(u8); // 初始化函数指针 u8 (*perused)(u8); // 内存使用率计算函数指针 u8 *membase[SRAMBANK]; // 内存池基地址数组 u16 *memmap[SRAMBANK]; // 内存池管理表基地址数组 u8 memrdy[SRAMBANK]; // 内存池初始化状态标志 }; extern struct _m_mallco_dev mallco_dev; // 声明全局内存管理设备 // 用户接口函数声明 void myfree(u8 memx, void *ptr); // 释放内存(外部调用) void *mymalloc(u8 memx, u32 size); // 分配内存(外部调用) u8 my_mem_perused(u8 memx); // 获取内存使用率(外部调用) #endif#include "malloc.h" #include <string.h> // 内部内存池(32字节对齐,便于DMA操作) __align(32) u8 mem1base[MEM1_MAX_SIZE]; // 内存管理表(记录每个内存块的状态) u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; void my_mem_init(u8 memx); u8 my_mem_perused(u8 memx); // 内存管理参数常量数组 const u32 memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE}; // 管理表大小 const u32 memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE}; // 内存块大小 const u32 memsize[SRAMBANK] = {MEM1_MAX_SIZE}; // 内存池总大小 // 全局内存管理设备实例 struct _m_mallco_dev mallco_dev = { my_mem_init, // 指向初始化函数 my_mem_perused, // 指向内存使用率函数 {mem1base}, // 内存池基地址(仅内部内存) {mem1mapbase}, // 内存管理表基地址 {0} // 初始化状态(0=未初始化) }; // 内存复制函数(内部使用) void mymemcpy(void *des, void *src, u32 n) { u8 *xdes = des; u8 *xsrc = src; while(n--)*xdes++=*xsrc++; // 逐字节复制 } // 内存设置函数(内部使用) void mymemset(void *s, u8 c, u32 count) { u8 *xs = s; while(count--)*xs++=c; // 逐字节设置 } // 内存池初始化(内部调用) void my_mem_init(u8 memx) { // 清零内存管理表(初始化所有块为空闲) mymemset(mallco_dev.memmap[memx], 0, memtblsize[memx]*2); // 标记内存池已初始化 mallco_dev.memrdy[memx]=1; } // 获取内存池使用率(内部调用) u8 my_mem_perused(u8 memx) { u32 used=0; // 遍历管理表,统计已用块数 for(u32 i=0;i<memtblsize[memx];i++) { if(mallco_dev.memmap[memx][i])used++; } // 计算并返回使用百分比 return (used*100)/(memtblsize[memx]); } // 内存分配核心算法(内部调用) u32 my_mem_malloc(u8 memx,u32 size) { signed long offset=0; u32 nmemb; // 需要的内存块数 u32 cmemb=0; // 当前找到的连续空闲块数 // 检查内存池是否初始化 if(!mallco_dev.memrdy[memx])mallco_dev.init(memx); // 计算需要的内存块数(向上取整) nmemb=size/memblksize[memx]; if(size%memblksize[memx])nmemb++; // 从内存池尾部向前搜索连续空闲块 for(offset=memtblsize[memx]-1;offset>=0;offset--) { if(!mallco_dev.memmap[memx][offset])cmemb++; // 空闲块计数 else cmemb=0; // 中断连续 // 找到足够的连续空闲块 if(cmemb==nmemb) { // 标记这些块为已分配(存储分配块数) for(u32 i=0;i<nmemb;i++) { mallco_dev.memmap[memx][offset+i]=nmemb; } return (offset*memblksize[memx]); // 返回偏移地址 } } return 0XFFFFFFFF; // 分配失败(内存不足) } // 内存释放(内部调用) u8 my_mem_free(u8 memx,u32 offset) { // 检查内存池是否初始化 if(!mallco_dev.memrdy[memx]) { mallco_dev.init(memx); return 1; // 返回未初始化错误 } // 检查偏移是否有效 if(offset<memsize[memx]) { // 计算块索引 int index=offset/memblksize[memx]; // 获取该块分配时记录的块数 int nmemb=mallco_dev.memmap[memx][index]; // 释放连续的内存块(标记为空闲) for(int i=0;i<nmemb;i++) { mallco_dev.memmap[memx][index+i]=0; } return 0; // 成功 } return 2; // 偏移超出范围 } // 释放内存(用户接口) void myfree(u8 memx,void *ptr) { if(ptr==NULL)return; // 空指针检查 // 计算偏移量(地址 - 基地址) u32 offset=(u32)ptr-(u32)mallco_dev.membase[memx]; my_mem_free(memx,offset); // 调用内部释放 } // 分配内存(用户接口) void *mymalloc(u8 memx,u32 size) { // 调用内部分配函数获取偏移 u32 offset=my_mem_malloc(memx,size); if(offset==0XFFFFFFFF)return NULL; // 分配失败 else return (void*)((u32)mallco_dev.membase[memx]+offset); // 返回绝对地址 }这些代码适合stm32f103c8t6使用嘛,能够分配内存
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@所谓伊人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值