extern void *memcpy(void *dest,void *src,unsigned int count);
#include <string.h>
功能:由src所指内存区域复制count个字符串到dest所指内存区域.
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针.
memset
extern void *memset(void *buffer,int c,int count);
#include <string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c
说明:返回指向buffer的指针.
二.区别
memset 用来对一段内存空间全部设置为某个字符,一般用于在对定义的字符串初始化为' '或者'\0';
例: char a[100];
memset(a,'\0',sizeof(a));
memcpy 是用来做内存拷贝,可以用来拷贝任何数据类型的对象,可以指定拷贝的数据长度;
例:
char a[100],b[50];
memcpy(b,a,sizeof(b)); //注意:如果使用sizeof(a),会造成内存溢出
mem是一段内存,他的长度,必须自己记住.memcpy是见着什么拷贝什么。
strcpy 就只能拷贝字符串,它遇到'\0'就结束拷贝;
例:char a[100],b[50];
strcpy(a,b);
如用strcpy(b,a)要注意a中的字符串长度(第一个'\0'之前) 是否超过50,如果超过,则会造成b的
内存溢出.它是不会拷贝'\0'的,所以一般还有加一个语句:
*a='\0';
三.使用技巧
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);
strcpy的原型为
char *strcpy(char *dest, const char *src)
而memcpy是给定来源和目标后,拷贝指定大小n的内存数据,而不管拷贝的内容是什么(不仅限于字符)
memcpy的原型为
void *memcpy(void *dest, const void *src, size_t n);
memcpy源码:
/***
*memcpy.c - contains memcpy routine *Purpose:
* memcpy() copies a source memory buffer to a destination buffer.
* Overlapping buffers are not treated specially, so propogation may occur.
*
**********/ #include <cruntime.h>
#include <string.h> #pragma function(memcpy) /***
*memcpy - Copy source buffer to destination buffer
*
*Purpose:
* memcpy() copies a source memory buffer to a destination memory buffer.
* This routine does NOT recognize overlapping buffers, and thus can lead
* to propogation.
*
* For cases where propogation must be avoided, memmove() must be used.
*
*Entry:
* void *dst = pointer to destination buffer
* const void *src = pointer to source buffer
* size_t count = number of bytes to copy
*
*Exit:
* Returns a pointer to the destination buffer
*
*Exceptions:
*******************************************************************************/ 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);
}
实现很简单,count一直减,把src值赋给dest,唯一值得注意的是函数原型。
void * __cdecl memcpy (
void * dst,
const void * src,
size_t count
) 可以看到参数为void 类型的指针,也返回一个void *指针。
我们可以利用void *类型指针为任何类型实现copy,如结构体:
struct A{
int x;
int y;
};
A *a=new A();
A *b=new A();
a->x=;
a->y=; memcpy(b,a,sizeof(A));
printf("%d%d\n",b->x,b->y);
输出53。
memset源码:
/***
*char *memset(dst, val, count) - sets "count" bytes at "dst" to "val"
*
*Purpose:
* Sets the first "count" bytes of the memory starting
* at "dst" to the character value "val".
*
*Entry:
* void *dst - pointer to memory to fill with val
* int val - value to put in dst bytes
* size_t count - number of bytes of dst to fill
*
*Exit:
* returns dst, with filled bytes
*
*Exceptions:
*
*******************************************************************************/ void * __cdecl memset (
void *dst,
int val,
size_t count
)
{
void *start = dst; #if defined (_M_IA64) || defined (_M_AMD64) { __declspec(dllimport) void RtlFillMemory( void *, size_t count, char ); RtlFillMemory( dst, count, (char)val ); } #else /* defined (_M_IA64) || defined (_M_AMD64) */
while (count--) {
*(char *)dst = (char)val;
dst = (char *)dst + ;
}
#endif /* defined (_M_IA64) || defined (_M_AMD64) */ return(start);
}
1.memmove
函数原型:void *memmove(void *dest, const void *source, size_t count)
返回值说明:返回指向dest的void *指针
参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数
函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。
2.memcpy
函数原型:void *memcpy(void *dest, const void *source, size_t count);
返回值说明:返回指向dest的void *指针
函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。
3.两者区别
函数memcpy() 从source 指向的区域向dest指向的区域复制count个字符,如果两数组重叠,不定义该函数的行为。
而memmove(),如果两函数重叠,赋值仍正确进行。
memcpy函数假设要复制的内存区域不存在重叠,如果你能确保你进行复制操作的的内存区域没有任何重叠,可以直接用memcpy;
如果你不能保证是否有重叠,为了确保复制的正确性,你必须用memmove。
memcpy的效率会比memmove高一些,如果还不明白的话可以看一些两者的实现:
void *memmove(void *dest, const void *source, size_t count)
{
assert((NULL != dest) && (NULL != source));
char *tmp_source, *tmp_dest;
tmp_source = (char *)source;
tmp_dest = (char *)dest;
if((dest + count<source) || (source + count) <dest))
{// 如果没有重叠区域
while(count--)
*tmp_dest++ = *tmp_source++;
}
else
{ //如果有重叠
tmp_source += count - 1;
tmp_dest += count - 1;
while(count--)
*--tmp_dest = *--tmp;
}
return dest;
}
void *memcpy(void *dest, const void *source, size_t count)
{
assert((NULL != dest) && (NULL != source));
char *tmp_dest = (char *)dest;
char *tmp_source = (char *)source;
while(count --)//不对是否存在重叠区域进行判断
*tmp_dest ++ = *tmp_source ++;
return dest;
}
memmove普通实现
memmove - Copy source buffer to destination buffer
;
;Purpose:
; memmove() copies a source memory buffer to a destination memory buffer.
; This routine recognize overlapping buffers to avoid propogation.
; For cases where propogation is not a problem, memcpy() can be used.
;
; Algorithm:
void* memmove(void* dest, void* source, size_t count)
{
void* ret = dest;
if (dest <= source || dest >= (source + count))
{
//Non-Overlapping Buffers
//copy from lower addresses to higher addresses
while (count --)
*dest++ = *source++;
}
else
{
//Overlapping Buffers
//copy from higher addresses to lower addresses
dest += count - 1;
source += count - 1;
while (count--)
*dest-- = *source--;l
}
return ret;
}
另一种实现:
void* mymemcpy( void* dest, const void* src, size_t count )
{
char* d = (char*)dest;
const char* s = (const char*)src;
// int n = (count + 7) / 8; // count > 0 assumed
int n = count >> 3;
switch( count & 7 )
{
do { *d++ = *s++;
case 7: *d++ = *s++;
case 6: *d++ = *s++;
case 5: *d++ = *s++;
case 4: *d++ = *s++;
case 3: *d++ = *s++;
case 2: *d++ = *s++;
case 1: *d++ = *s++;
case 0 } //while (--n > 0);
while (n-- > 0)
}
return dest;
}
C的memset,memcpy,strcpy 的区别 及memset memcpy memmove源码的更多相关文章
-
gcc和g++的区别【转自中国源码网】
gcc和g++的区别[转自中国源码网] gcc和g++都是GNU(组织)的一个编译器. 误区一:gcc只能编译c代码,g++只能编译c++代码两者都可以,但是请注意:1.后缀为.c的,gcc把它当作是 ...
-
python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)
python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...
-
面试题:HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基 ...
-
HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
Hashmap本质是数组加链表.根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap:在hashMap的基 ...
-
HashMap和ConcurrentHashMap的区别,HashMap的底层源码
HashMap本质是数组加链表,根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap在HashMap的基础 ...
-
vue打包时,assets目录 和static目录下文件的处理区别(nodeModule中插件源码修改后,打包后的文件应放在static目录)
为了回答这个问题,我们首先需要了解Webpack如何处理静态资产.在 *.vue 组件中,所有模板和CSS都会被 vue-html-loader 及 css-loader 解析,并查找资源URL.例如 ...
-
memcpy、memmove、memset及strcpy函数实现和理解
memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...
-
c语言中几个常见的库函数strlen、strcmp、strcat、strcpy、strncpy、memset、memcpy、memmove、mmap
1.strlen() 1)计算给定字符串的长度,不包括’\0’在内 unsigned int strlen(const char *s) { assert(NULL != s);//如果条件不满足,则 ...
-
memmove和memcpy函数的区别及实现
一.memmove()和memcpy()函数和strcpy()函数的区别: (1)使用的类型不同,strcpy()函数只对字符串进行操作:memmove()和memcpy()函数对所有类型都适用,为内 ...
随机推荐
-
理解Java对象序列化
http://www.blogjava.net/jiangshachina/archive/2012/02/13/369898.html 1. 什么是Java对象序列化 Java平台允许我们在内存中创 ...
-
UVa 11889 Benefit(数论)
题目链接: 传送门 Benefit Time Limit: 5000MS Memory Limit: 32768 KB Description Recently Yaghoub is play ...
-
【Struts2学习笔记(1)】Struts2中Action名称的搜索顺序和多个Action共享一个视图--全局result配置
一.Action名称的搜索顺序 1.获得请求路径的URI,比如url是:http://server/struts2/path1/path2/path3/test.action 2.首先寻找namesp ...
-
2017C语言程序设计预备作业
Deadline:2017-9-30 23:00 一.学习使用MarkDown 本学期的博客随笔都将使用MarkDown格式,要求熟练掌握MarkDown语法,学会如何使用标题,插入超链接,列表,插入 ...
-
js中严格模式
我们在js中可以使用"use strict";定义了我们在接下来的文档输写中 将按照严格模式进行: function(){ "use strict'; ;// 在这里我们 ...
-
循环中else的用法
name = 'hello' for x in name: print(x) if x == 'l': break #退出for循环 else: print("==for循环过程中,如果没有 ...
-
Delphi连接MySql(待测试验证,使用mysql.pas未通过)
要在一个Delphi程序中调用Mysql数据库,查到有个资料如下,待验证,验证后会给出结果.暂时做个标记 已经验证,验证日期:2018.6.18 验证结果:不可行 验证工具:XE7,mysql5.5. ...
-
Codeforces Round #432 Div. 1
A:大胆猜想合法点不会很多,于是暴力检验,一旦发现不合法就break,可以random_shuffle一下. #include<iostream> #include<cstdio&g ...
-
Django中简单添加HTML、css、js等文件(非正规添加,适合小白)
Django中简单添加HTML.css.js等文件 首先申明下自己的环境, python版本3.65(亲测3.7版本有毒,没解决掉!) Django版本1.11.15(版本比较成熟,也可以用最新的版本 ...
-
rac数据库单连接报错ora-12537解决办法
1.现象如下: C:\Users\Administrator.DBA-PC>sqlplus sys/oracle@192.168.100.33:1521/orcl as sys dba SQL* ...