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