memory库函数的实现

下面主要对常用的几个memory库函数的实现(memcpy、memmove、memset、memcmp):

memcpy函数与memmove函数:

相同点:

  两者实现的功能均为从src拷贝count个字符到dest。

不同点:

  1、memcpy函数不考虑内存是否有覆盖的问题,也就是说他只负责完成拷贝工作,至于拷贝后的值正确与否,它是不理会的。

  2、memmove函数考虑了内存覆盖的问题:1)当无覆盖情况时,功能及拷贝结果与memcpy函数相同;

                      2)当有内存覆盖时,能够确保拷贝后的值得正确性。

  3、内存无覆盖及有覆盖的情况如下:

代码实现如下

//memcpy:内存拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。

char* my_memcpy(char* dst,const char* src,size_t count){	assert(dst != NULL);	assert(src != NULL);	assert(count <= strlen(src)+1);	char* pDst = dst;	const char* pSrc = src;	while (count--)	{		*pDst = *pSrc;		pDst++;		pSrc++;	}	return dst;}--------------------------------------------------------------------------------------------------------------------------------------------

/* memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前

将重叠区域的字节拷贝到目标区域中。但复制后src内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。*/

char* my_memmove(char* dst,const char* src,size_t count){	assert(dst != NULL);	assert(src != NULL);	assert(count <= strlen(src) + 1);	char* pDst = dst;	const char* pSrc = src;	if (pDst > pSrc + count || pDst < pSrc)//不包含内存覆盖	{		//正向拷贝		while (count--)		{			*pDst = *pSrc;			pDst++;			pSrc++;		}	}	else//存在内存覆盖问题	{		//反向拷贝(从尾到头)		pDst += count;		pSrc += count;
		while (count--)		{			*pDst = *pSrc;			pDst--;			pSrc--;		}		}	return dst;}
---------------------------------------------------------------------------------------------------------------------------------------------------------------- 

memset函数:将str所指内存区域的前count个字节设置成字符c。(注:该函数是对字节进行设置)

//memset内存设置函数:将str所指内存区域的前count个字节设置成字符c。

代码实现如下:void* my_memset(void* str, int c, int count){	assert(str != NULL);	char* pStr = (char*)str;	while (count--)	{		*pStr = c;		pStr++;	}	return str;

}

  1、情况一:对字符数组进行设置

    int main()
    {
      char a[10];
      memset(a , 0 , 10 );
    }    数组a是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。

  2、情况二:对整形数组进行设置

    int main()
    {
      int b[10];
      memset(b , 0 , 10 );
    }

    数组b是整型的,而使用 memset是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009。而非想要的1。

  3、  如果用memset(a,1,20),就是对a指向的内存的20个字节进行赋值,每个都用数1去填充,转为二进制后,1就是00000001,占一个字节。

    一个int类型占4字节,合一起是0000 0001,0000 0001,0000 0001,0000 0001,转化成十六进制就是0x01010101,就等于16843009,

    

    就完成了对一个int元素的赋值了。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//memcmp是比较内存区域str1和str2的前count个字节。该函数是按字节比较的。

int my_memcmp(const void *str1, const void *str2, size_t count){	if (str1 == NULL && str2 == NULL)	{		return 0;	}	const char* pStr1 = (const char*)str1;	const char* pStr2 = (const char*)str2;	int res = 0;	for (pStr1, pStr2; count > 0; ++pStr1, ++pStr2, --count)	{		res = *pStr1 - *pStr2;		if (res != 0)			break;

	}	return res;}
				
时间: 2024-10-31 11:40:12

memory库函数的实现的相关文章

《C与指针》第九章练习

本章问题 1.C语言缺少显示的字符串数据类型,这是一个优点还是一个缺点? answer: (这个问题存在争论(尽管我有一个结论))目前这个方法的优点是字符数组的效率和访问的灵活性,它的缺点是有可能引起错误,数组溢出,下标越界,不能改变任何用于保存字符串的数组的长度等.我的结论是从现代的面向对象的奇数引出的,字符串类毫无例外的包括了完整的错误检查,用于字符串的动态内存分配和其他一些防护措施,这些措施都会造成效率上的损失,但是,如果程序无法运行,效率再高也没有什么意义,况且,现在软件项目的规模比设计

虚拟内存 Virtual Memory

物理地址和虚拟地址 把主存看成是由连续字节单元组成的大数组,并且用物理地址(PA)来标识每个数组的单元.CPU需要加载存储器中一个字都时候,就指定这个字的物理地址的首地址,从而将存储器中的数据返回给CPU,通过物理地址来访问存储器的方式就是物理寻址.所以很直观,物理寻址方便很多,然而对于系统来说,直接物理寻址对存储器的管理很不合理.  所以有了虚拟地址(VA),通过虚拟地址访问存储器的方式就叫做虚拟寻址,其实这种说法不是很恰当,因为虚拟地址最终还是会被翻译(这个翻译由硬件和系统协同完成的)成物理

openssl库函数使用中的SSL_shutdown、SSL_free不能同时使用

openssl库函数中提供了两个销毁ssl连接通道的函数:SSL_shutdown.SSL_free,作用相同,二者取其一,不可同时使用,否则就会出现两次销毁对象的报错. 请看下面一个代码片段: ...... if (SSL_shutdown(ssl) != 1) { close(sfd); printf("ssl shutdown failed\n"); } SSL_free(ssl); ...... 使用-lssl参数编译可以成功,但在运行时,会概率性出现double free o

使用cublas 矩阵库函数实现矩阵相乘

2014-08-10 cublas中执行矩阵乘法运算的函数 首先要注意的是cublas使用的是以列为主的存储方式,和c/c++中的以行为主的方式是不一样的.处理方法可参考下面的注释代码 // SOME PRECAUTIONS: // IF WE WANT TO CALCULATE ROW-MAJOR MATRIX MULTIPLY C = A * B, // WE JUST NEED CALL CUBLAS API IN A REVERSE ORDER: cublasSegemm(B, A)!

stm32 DMA数据搬运 [操作寄存器+库函数](转)

源:stm32 DMA数据搬运 [操作寄存器+库函数] DMA(Direct Memory Access)常译为“存储器直接存取”.早在Intel的8086平台上就有了DMA应用了. 一个完整的微控制器通常由CPU.存储器和外设等组件构成.这些组件一般在结构和功能上都是独立的,而各个组件的协调和交互就由CPU完成.如此一来,CPU作为整个芯片的核心,其处理的工作量是很大的.如果CPU先从A外设拿到一个数据送给B外设使用,同时C外设又需要D外设提供一个数据...这样的数据搬运工作将使CPU的负荷显

C语言库函数大全及应用实例九

原文:C语言库函数大全及应用实例九                                                [编程资料]C语言库函数大全及应用实例九 函数名: mktemp 功 能: 建立唯一的文件名 用 法: char *mktemp(char *template); 程序例: #i nclude #i nclude int main(void) { /* fname defines the template for the temporary file. */ char

C语言库函数大全及应用实例十

原文:C语言库函数大全及应用实例十                                             [编程资料]C语言库函数大全及应用实例十 函数名: qsort 功 能: 使用快速排序例程进行排序 用 法: void qsort(void *base, int nelem, int width, int (*fcmp)()); 程序例: #i nclude #i nclude #i nclude int sort_function( const void *a, con

C语言库函数大全及应用实例十一

原文:C语言库函数大全及应用实例十一                                         [编程资料]C语言库函数大全及应用实例十一 函数名: setbkcolor 功 能: 用调色板设置当前背景颜色 用 法: void far setbkcolor(int color); 程序例: #i nclude #i nclude #i nclude #i nclude int main(void) { /* select a driver and mode that sup

linux内核系统调用和标准C库函数的关系分析

今天研究了一下系统调用和标准库函数的区别和联系,从网上搜集的资料如下: 1.系统调用是为了方便应用使用操作系统的接口,而库函数是为了方便人们编写应用程序而引出的,比如你自己编写一个函数其实也可以说就是一个库函数. 2.系统调用可以理解为内核提供给我们在用户态用的接口函数,可以认为是某种内核的库函数. 3.read就是系统调用,而fread就是C标准库函数. 4.很多c函数库中的函数名与系统调用的名称一样是因为该函数本身其实就是调用的系统调用,放到c函数库就是为了用户态的使用 5.写程序直接使用的