9. memcpy() memccpy() memmove() strcpy() memset()
部分参考: http://www.cppblog.com/kang/archive/2009/04/05/78984.html
表头文件: #include <string.h>
定义函数: void *memcpy(void *dest, const void *src, size_t n)
函数说明: memcpy()用来拷贝src所指的内存内容前n个字节到dest所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束
strcpy()只能用于字符串的copy,而memcpy()可用于任意类型,包括数组、结果体、对象(硬拷贝);此外,memcpy被编译优化为MOVSB, MOVSW等的机器码内存块
搬动,有的例程上说 memcpy实现是用int类型,每次拷贝4个字节。strcpy是单个字节拷贝的。
返回值: 返回指向dest的指针
表头文件: #include <string.h>
定义函数: void *memccpy(void *dest, const void *src, int c, size_t n);
函数说明: memccpy()用来拷贝src所指的内存内容前n个字节到dest所指的地址上。与memcpy()不同的是,memccpy()如果在src中遇到某个特定值(int c)立即停止复制。
返回值: 返回指向dest中值为c的下一个字节指针。返回值为0表示在src所指内存前n个字节中没有值为c的字节。
表头文件: #include <string.h>
定义函数: void *memmove(void *dest, const void *src, size_t n);
函数说明:memmove()是从一个缓冲区移动到另一个缓冲区中。 该函数把源字符串拷贝到临时buf里,然后再从临时buf里写到目的地址,增加了一次不必要的开销。性能较memcpy低。
返回值: 返回指向dest指针。
当 dest <= src-count 或 dest >= src+count 时,以上三个函数均不会产生覆盖问题,即源数据不会被更改。
若不在以上范围内,则源数据会被更改。此时,memcpy(), memccpy()的行为是未定义的(有的库考虑了重叠,有的没有考虑,vs貌似考虑了),只能使用更为安全但性能较低的memmove().
如:
char a[]={'a','b'};
char b[]={'c','d','e','f','g','h'};
memmove(a,b,sizeof(b));
发现即使a数组指向的空间不够存储数据,也能够移动成功。
若:
char *p=b+2;
memmove(p,b,sizeof(b));
输出数据会发现b中数据输出已被更改。
原因|dest - src |<count,出现覆盖问题。也就是说如果外部分配给的空间不足以存储要拷贝的数据时,就有可能出现源数据被覆盖更改的问题。
如果在使用这些函数时,分配给足够的空间,然后再使用就不会出现覆盖问题。
表头文件: #include <string.h>
定义函数: extern void *memset(void *buffer, int c, int count);
功能: 把buffer所指内存区域的前count个字节设置成字符 c。如' ' , '\0' 。通常用来赋值字符数组 及 清空各类型(用0清空)数组。
说明: 返回指向buffer的指针。
对于int数组,有:
int a[5];
使用
memset(a, 0, sizeof(int)*5); // 可以用0来清空数组a,a中各元素值为 00000000 00000000 00000000 00000000,即 0.
而
memset(a, 1, sizeof(int)*5);
原本想要给a赋值1, 结果会给每个int(4个字节)的每个字节赋值为00000001, 结果每个int值为 00000001 00000001 00000001 00000001,即 16843009,而不是1了。
自定义这些函数:
考虑内存重叠的 memcpy
void* Memcpy(void* dst , const void* src, size_t n)
{
if (dst == NULL || src == NULL)
{
return NULL;
}
char* pDst = static_cast<char*>(dst); // (char*)dst;
char* pSrc = const_cast<char*>(static_cast<const char*>(src)); // (char*)src;
if (pDst > pSrc && (pSrc + n) > pDst) // 只有当dst 在 src 之后,且 (src + n) > dst时, 会将之前copy的内容覆盖掉,故此时因自后向前拷贝
{
while (n > )
{
n--;
*(pDst + n) = *(pSrc + n);
}
}
else // 其他情况,都从前往后拷贝
{
int i = ;
while (i < n)
{
*(pDst + i) = *(pSrc + i);
i++;
}
}
return dst;
}
strcpy
char* Strcpy(char* dst, const char* src)
{
if (dst == NULL || src == NULL)
{
return NULL;
}
while ( (*dst++ = *src ++) != '\0'); // 先取值,再++
return dst;
}
9. memcpy() memccpy() memmove() strcpy() memset()的更多相关文章
- memcpy、memmove、memset及strcpy函数实现和理解
memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ...
- strcpy()、memcpy()、memmove()、memset()的内部实现
一直想知道 strcpy().memcpy().memmove().memset()的内部实现 strcpy(), 字符串拷贝. char *strcpy(char *strDest, const c ...
- memcpy、memmove、memset、memchr、memcmp、strstr详解
第一部分 综述 memcpy.memmove.memset.memchr.memcmp都是C语言中的库函数,在头文件string.h中.memcpy和memmove的作用是拷贝一定长度的内存的内容,m ...
- memcpy、memmove、memset
void * memcpy(void * dst, const void * src, size_t count) { void *res=dst; while (count--) { *(char* ...
- memmove和memcpy 以及strcmp strcpy几个库函数的实现
memmove和memcpy 1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向 ...
- 不使用库函数、自己编写的(strlen、strcpy、strcmp、strcat、memcmp、memcpy、memmove)
不使用库函数.自己编写的(strlen.strcpy.strcmp.strcat.memcmp.memcpy.memmove) //求字符串长度的函数 int my_strlen(const char ...
- memcpy与memmove的区别
在面试中经常会被问道memcpy与memove有什么区别? 整理如下: 其实主要在考C的关键字:restrict C库中有两个函数可以从一个位置把字节复制到另一个位置.在C99标准下,它们的原型如下: ...
- 关于memcpy和memmove的一点说明
今天看到书上降到memcpy和memmove的区别才突然发现原来两者之间有如此区别,以前只知道这两个函数是 实现同样的功能,没有接触到其不同. memcpy和memmove在MSDN的定义如下: 从两 ...
- C/C++之Memcpy and memmove
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中. 但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开 ...
随机推荐
- UNDERSTANDING VOLATILE VIA EXAMPLE--reference
We have spent last couple of months stabilizing the lock detection functionality in Plumbr. During t ...
- gridview添加header
gridview是不能添加header的,这里的解决方法是将listview改造成gridview使用,功能很好用,唯一的缺点是列数不能自适应 示例代码下载地址http://pan.baidu.com ...
- HDU 5119 Happy Matt Friends(dp+位运算)
题意:给定n个数,从中分别取出0个,1个,2个...n个,并把他们异或起来,求大于m个总的取法. 思路:dp,背包思想,考虑第i个数,取或者不取,dp[i][j]表示在第i个数时,异或值为j的所有取法 ...
- AS Gradle构建工具与Android plugin插件【大全】
Android plugin version 与 gradle version 的关系 Gradle是一种构建工具,它通过编写一个名为build.gradle的脚本文件对项目进行设置,再根据这个脚本对 ...
- firebug中console命令尝试
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- updatepanel的用法之triggers
triggers有的两种触发器asyncpostbacktrigger和postbacktrigger.asyncpostbacktrigger(异步回调触发器):局部刷新,只刷新updatepane ...
- 关于Core Data的一些整理(三)
关于Core Data的一些整理(三) 关于Core Data Stack的四种类与它们的关系如下: NSManagedObjectModel NSPersistentStore NSPersiste ...
- iOS-点击视图,视图背景颜色随机更改
一.效果图 二.代码 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the v ...
- 什么是NSAssert?
断言, 判断是否符合某个特定条件, 符合就继续运行程序, 反之就抛出异常, 后面为自定义错误提示, 也可以使用NSParameterAssert, 在调试上有着很大的方便 int a = 0; NSA ...
- 『重构--改善既有代码的设计』读书笔记----Introduce Explaning Variable
有时候你会遇到一系列复杂的表达式连续运算的时候,这个时候你可能根本招架不住如此长或者是如此复杂的长函数.这个时候你可以通过引用临时变量来储存他们的结果,将这些长函数的结果分成一个个临时变量来让函数清晰 ...