memset ,memcpy,strcpy作用与区别

memset   主要应用是初始化某个内存空间。                  
memcpy   是用于copy源空间的数据到目的空间中。                  
strcpy   用于字符串copy,遇到‘\0’,将结束。


一、 strcpy  
    strcpy    extern char *strcpy(char *dest,char *src);    
    #include <string.h>    
   功能
:把src所指由NULL结束的字符串复制到dest所指的数组中    
    说明:  src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。    返回指向dest的指针   
char   *strcpy(char   *strDest,const   char   *strSrc)   
{   
        assert((strDest!=NULL)&&(strSrc   !=NULL))   //判断指针是否合法,即分配内存,指向某块确定区域
        char   *address   =   strDest;                     //记住目标地址的起始值
        while((*strDest++   =   *strSrc++)!='\0')   //先拷贝,后判断,这样就不用在拷贝完了后,再加一句
              NULL;                                                     // *strDest = '\0'; -->即加一个结束符.因为字符串结束已拷贝了.
              return   address;                                 //返回目标首地址的值。             
               }


假如有如下代码,请问输出为多少?
  #include "stdio.h"
            main()
                {  char dest[3];
                    char str[6]="Hello";
                    strcpy(dest,str); 
                    printf("%s\n",dest);
              }


编译输出如下结果:
        Hello                  //没有输出乱码,有点怪怪的为什么?
       分析: 1>str中字符串的长度大于dest 的内存长度3.为什么str字符串还能完拷贝到dest 中呢?
             在调用   strcpy(dest,str);  时,while((*strDest++   =   *strSrc++)!='\0')   
            没有判断strDest的内存是否够,而是将srtSrc的内容直接拷贝到strDest,当拷到'\0'就结束.
            因此在使用printf("%s\n",dest);  时 输出遇到'\0'时停此输出.所以会输出: Hello


二、memset

    #include <string.h>    

void *memset(void *s, int ch, size_t n);

  函数解释:将s中前n个 字节替换为ch并返回s;
  memset:作用是在一段内存块中填充某个给定的值,它是对较大的 结构体数组进行清零操作的一种最快方法

    例如:     
           char a[10];                         
           memset(a, '\0', sizeof(a));                

           memset可以方便的清空一个结构类型的变量数组。        
   

例如:
struct    _test{  
char s[10];      

                                int x;      
                                int y;
};        
    变量     struct _test    st;              
(1)一般清空st的方法如下: 
st.s[0] = '\0'; st.x =0;   st.y =0;               
(2) 用memset方法如下:                
             memset(&st,0,sizeof(struct _test));         
    数组:  struct _test     st[10];                
  memset(st,0,sizeof(struct _test)*10);  //清空方法 
//memset 源码的实现 C语言
#include <mem.h> 
void* memset(void* s, int c, size_t n)
{
     unsigned char* p = (unsigned char*) s;
     while (n > 0) 
       {
               *p++ = (unsigned char) c;
                --n;
       }
      return s;
  }
memset 可以方便的清空一个数据结构的变量或数组.      
        如:         struct sample_struct  {  
                                  char   csName[16];               
                                  int      iSeq;              
                                  int       iType;        
                                    };        
       对于变量   struct sample_struct   stTest;          一般情况下,初始化stTest的方法:         
                         stTest.csName[0]='\0';         
                         stTest.iSeq=0;         
                         stTest.iType=0;     
        而用memset:        
                   memset(&stTest,0,sizeof(struct sample_struct));    
        如果是数组: struct sample_struct   TEST[100];     
                   memset(TEST,0,sizeof(struct sample_struct)*100);






三、memcpy
    memcpy   extern void *memcpy(void *dest,void *src,unsigned int count);  
    #include <string.h>    
    功能:由src所指内存区域复制count个字符串到dest所指内存区域.    
    说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针. 可以拿它拷贝任何数据类型的对象。    
             例如:  char a[10],b[5];              
                        memcpy(b, a, sizeof(b));             /*注意如果用sizeof(a),会造成b的内存地址溢出*/


面试时写以下代码的分析(不正确)
void memcpy(void *dest, void *src, int len)
{
      void *p = dest;
      void *q = src;
      if( dest == NULL ||src == NULL)
      {
          return;
      }
 
      for (int i=0; i<len; i++)
     {
            *p++ = *q++;
     }
}
1、函数原型应该是 void*memcpy(void* dest,const void* src,size_t count),虽然面试官给我写的原型也是错的,但是我应该早点看看的。
2、按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,即不能对void指针进行如p++的操作,所以需要转换为具体的类型指针来操作,例如char *。
3、memcpy是对内存进行操作,可能遇到内存重叠的情况,同样的问题存在于memmove中, 但是源代码中这两个函数的处理方式不一样:
     1)、memcpy中dest和source中的区域不能重叠,否则会出现未知结果中dest和source中的区域不能重叠,否则会出现未知结果。函数没做
     任何内存的处理,内存是否重叠由程序员自己控制。
     2)、memmove里面则判断了内存重叠的情况,当内存重叠时从后往前复制,以确保复制正常处理。 
源码如下:
void * __cdecl memcpy (void * dst, const void * src,size_t count  )
{
        void * ret = dst;
#if defined (_M_IA64)
        {
        __declspec(dllimport)


        void RtlCopyMemory( void *, const void *, size_t count );


        RtlCopyMemory( dst, src, count );


        }


#else  /* defined (_M_IA64) */
        /*
         * copy from lower addresses to higher addresses
         */
        while (count--) {
                *(char *)dst = *(char *)src;
                dst = (char *)dst + 1;
                src = (char *)src + 1;
        }
#endif  /* defined (_M_IA64) */


        return(ret);
}








from:  http://blog.csdn.net/zhongshch/article/details/6529212
http://www.cnblogs.com/glguan/archive/2012/05/15/2500843.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值