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指针,用作返回值
  • 4、这里有一个技巧,如果写成以下两种,面试的时候会大大扣分!
//第一种
while(*dst++ = *src++)  //直接越界访问,没有检查指针的有效性
//第二种
while(*src!='\0'){*dst++ = *src++;}//考虑了src的边界问题,没有在dst的后面加'\0',会导致dst的长度未知引起错误
  • 5、函数返回dst的原始值是为了能够支持链式表达式,增加了函数的附加性。

上述第5点可以用如下测试代码来说明:

int length = strlen(strcpy(strA,strB));//如果不支持链式表达式,这里会报错。

那么有时候也会问为什么不返回src的原始值,错误原因有以下三点:

  • 源字符串本来就已知,返回没有什么意义
  • 不能支持形如char * strA = strcpy(new char[10],strB) 这样的表达式
  • 为了保护源字符串,使用const限定了src所指的内容,把const char作为char的返回值,类型不符,编译器会报错。

strcpy和memcpy的不同点

这个也是常见的考点,主要分为以下三点不同:

  • 复制内容不同:strcpy只能复制字符串,而memcpy可以复制任何内容,例如字符数组,整型,结构体等
  • 复制的方法不同:strcpy不需要指定长度,它遇到字符串结束符’\0’才结束,所以容易溢出。memcpy则需要传入第三个参数来指定长度
  • 用途不同:通常在复制字符串的时候用strcpy,而需要复制其他数据类型的时候则一般用memcpy。

C/C++的mem函数和strcpy函数的区别和应用的更多相关文章

  1. strcmp函数和strcpy函数

    (一)strcmp函数 strcmp函数是比較两个字符串的大小,返回比較的结果.一般形式是: i=strcmp(字符串,字符串); 当中,字符串1.字符串2均可为字符串常量或变量:i   是用于存放比 ...

  2. strlen函数,strcat函数,strcpy函数,strncpy函数,strcmp函数

    strcpy函数: char *strcpy(char *Dest , const char *Src) { assert((Dest != NULL) && (Src != NULL ...

  3. 编写函数模拟strcpy()函数功能

    strcpy(字符数组1,字符串2) strcpy( )用于将字符串2复制到字符数组1中 /* strcpy(字符数组1,字符串2) strcpy( )用于将字符串2复制到字符数组1中 模拟strcp ...

  4. strcpy函数的实现

    strcpy函数的实现 大家一般认为名不见经传strcpy函数实现不是很难,流行的strcpy函数写法是: char *my_strcpy(char *dst,const char *src) { a ...

  5. strcpy函数实现

    1,strcpy最简便实现 char * strcpy_to (char *dst, const char *src) { char *address = dst; assert((dst != NU ...

  6. strcpy函数和strncpy函数的区别

    strcpy函数和strncpy函数的原型介绍在我的另一篇文章中介绍了,见strcpy,strncpy,strlen等函数原型 strcpy:字串复制 原型:char *strcpy(char *de ...

  7. memcpy、memmove、memset及strcpy函数实现和理解

    memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...

  8. strlen() 和 strcpy()函数

    strlen() 和 strcpy()函数的区别,这两个一个是返回一个C风格字符串的长度,一个是对一个C风格字符串的拷贝,两个本来功能上是不同的,此外,他们还有一些细小的区别:strlen(" ...

  9. strcpy函数的C/C++实现

    2013-07-05 14:07:49 本函数给出了几种strcpy与strncpy的实现,有ugly implementation,也有good implementation.并参考标准库中的imp ...

随机推荐

  1. [SCOI 2012]滑雪与时间胶囊

    Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...

  2. [CQOI2013]棋盘游戏

    Description 一个n*n(n>=2)棋盘上有黑白棋子各一枚.游戏者A和B轮流移动棋子,A先走. A的移动规则:只能移动白棋子.可以往上下左右四个方向之一移动一格. B的移动规则:只能移 ...

  3. 51 nod 1394 1394 差和问题(线段树)

    1394 差和问题基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个多重集合S(即里面元素可以有重复),初始状态下有n个元素,对他进行如下操作: 1.向S里面添 ...

  4. FFT模板(BZOJ2179)

    实现了两个长度为n的大数相乘. #include <cstdio> #include <cmath> #include <complex> using namesp ...

  5. SpringCloud学习之Hystrix

    一.为什么要有断路器 在分布式系统当中,服务之间调用关系会随着业务的发展而变的复杂,一个服务可能依赖多个服务,服务之间层层依赖也是家常便饭的事情,如果一个服务的瘫痪很有可能导致整个系统的崩溃.比如说, ...

  6. spring 自定义事件发布及监听(简单实例)

    前言: Spring的AppilcaitionContext能够发布事件和注册相对应的事件监听器,因此,它有一套完整的事件发布和监听机制. 流程分析: 在一个完整的事件体系中,除了事件和监听器以外,还 ...

  7. Windows提示dll组件丢失

    我们在运行一些软件时,常常会遇到这种问题.下面就来提供解决办法: 登陆网址:www.dll-files.com. 找到页面的搜索部分,并且进行相关搜索: 下图显示了相关的dll下载链接. 下载解压即可 ...

  8. SynchronizedMap和ConcurrentHashMap的深入分析

    http://blog.sina.com.cn/s/blog_5157093c0100hm3y.html java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashM ...

  9. Python里面 search0和 match0的区别?

    这是正则表达式里面的函数: match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配: 也就是说match()只有在0位置匹配成功的话才有返回,如 ...

  10. 腾讯云H5语音通信QoE优化

    本文首发在云+社区,未经许可,不得转载. 云+导语:4月21日,腾讯云+社区在京举办"'音'你而来,'视'而可见--音视频技术开发实战沙龙",腾讯音视频实验室高级工程师张轲围绕网络 ...