C/C++的mem函数和strcpy函数的区别和应用

mem系列函数是面试的时候常考的知识点,我们需要熟练掌握这三个函数的原理和代码实现,要能准确无误的写出代码。

memcpy、memset和memset三个函数在使用过程中,均需包含以下头文件:

//在C中 #include <string.h> //在C++中 #include <cstring> memcpy

memcpy函数是C/C++中的内存拷贝函数,它的功能是从源src所指的内存地址的起始位置开始,拷贝n个字节到目标dst所指的内存地址的起始位置中。

研究函数功能最好的办法就是研究其源代码,这里在网上找了一份,如下:

void * __cdecl memcpy ( void * dst,const void * src,size_t count) { void * ret = dst; while (count--) { // 注意, memcpy函数没有处理dst和src区域是否重叠的问题 *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } return(ret); }

源代码比较简单,定义一个计数,然后从头到尾一次将src指向的值拷贝给dst,库函数中的memcpy不能处理dst和src中存在重叠部分这种情况。

那么处理重叠部分的话,我们可以采用从后往前依次拷贝的方法,下面给出我修改过的函数代码:

void * __cdecl memcpy ( void * dst,const void * src,size_t count) { char *pDst = static_cast<char *> dst; const char *pSrc = static_cast<const char *> src; //检查参数 if(pDst==NULL || pSrc== NULL || count <=0){ return NULL; } //判断有是否存在重叠部分 if(pDst > pSrc && pDst < pSrc + count){ for(size_t i=count-1; i>=0; i--) { pDest[i] = pSrc[i]; } } else { for(size_t i=0; i<count; i++) { pDest[i] = pSrc[i]; } } return pDst; } memset

memset一般用于对内存初始化,在这里需要注意的是,memset函数是对内存的每个字节(按字节)设置成c的值。其函数原型如下:

void memset(void *s, int c, size_t n) { const unsigned char uc = c;//将int转换成char,截去c的高24位,留下低8位 unsigned char *su; for (su = s; 0 < n; ++su, --n) *su = uc; return s; }

注意,这里有一个坑,memset一般用于将内存清零,你要是想将这段内存初始化为1而写下下面的代码:

int num[10]; memset(num,1,sizeof(int)*10);

这里并不会如你所愿,num的每一个数都被初始化为16843009,原因就是上述提到的会截去c的高24位。

使用memset初始化比用for循环初始化要快很多,所以在初始化基本类型数据,结构体等的时候尽量选择memset,memset可以方便的清空一个结构类型的变量或数组。

memmove

它与memcpy的功能相似,都是将src所指的n个字节复制到dst所指的内存地址的起始位置,不同的是它处理了src和dst有重叠的情况。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。(与上述修改过得memcpy基本一致)

所以基本原则就是,如果你能确保两段内存没有重叠的部分,就使用memcpy来进行拷贝;如果你不能确定,为了保证复制的正确性,必须用memmove。
其实现代码如下:

void* memmove(void* dest, void* src, size_t count) { void* ret = dest; if (dest <= src || dest >= (src + count)) { //Non-Overlapping Buffers //copy from lower addresses to higher addresses while (count --) *dest++ = *src++; } else { //Overlapping Buffers //copy from higher addresses to lower addresses dest += count - 1; src += count - 1; while (count--) *dest-- = *src--; } return ret; } strcpy

strcpy是C语言的标准库函数,使用strcpy需要包含以下头文件:

#include <string.h> #include <stdio.h>

其函数功能是把从src地址开始且含有NULL结束符的字符串复制到dst开始的地址空间,返回指向dst的指针。其函数代码如下:

char* strcpy(char* dst , char* src){ if(dst==NULL||src==NULL) return NULL;// --1 if(dst==src) return dst; //--2 char* address = dst; //--3 while((*dst++ = *src++)!='\0') //--4 return address; //--5 }

图中标出来的都是考点,下面一一说明:

1、需要判断参数的正确性,这里也可以抛出一个异常

2、如果指向了同一块内存,不用复制直接返回即可

3、这里需要保存原始的dst指针,用作返回值

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/86161f9442f870038f92a06bc7124bd2.html