1、memcpy 函数用于 把资源内存(src所指向的内存区域) 复制到目标内存(dest所指向的内存区域);拷贝多少个?有一个size变量控制
拷贝的字节数;
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
使用方法:(1)能够拷贝不论什么类型的对象,由于函数的參数类型是void*(没有定义类型指针),也就是说传进去的实參能够是int*,short*,char*等等,
可是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节,呵呵
函数源码实现:
void *memcpy1(void *desc,const void * src,size_t size)
{
 if((desc == NULL) && (src == NULL))
 {
  return NULL;
 }
 unsigned char *desc1 = (unsigned char*)desc;
 unsigned char *src1 = (unsigned char*)src;
 while(size-- >0)
 {
  *desc1 = *src1;
  desc1++;
  src1++;
 }
 return desc;
}

int _tmain(int argc, _TCHAR* argv[])
{
 int dest[2] = {0};
 const char src[5] = "1234";
 //printf(src);
 memcpy1(dest,src,sizeof(src));
 //*(dest+5) = '/0';
 printf((char *)dest);
 int m = -1;
 return 0;
}
注意事项:(1)void* 一定要返回一个值(指针),这个和void不太一样!
          (2)首先要推断指针的值不能为空,desc为空的话肯定不能拷贝内存空间,src为空相当于没有拷贝;所以之间return掉;
          (3)""空串是指内容为0,NULL是0,不是串;两个不等价;
          (4)int dest[2] = {0};这是对int 类型的数组初始化的方法;假设是char类型,就用char a[5] = "1234";  注意数组下标要
               多于实际看到的字符数,由于还有'/0'
          (5)printf((char *)dest);这句话,是把 char 类型 src 传到 int 类型的 dest的内存强制转化成char类型,然后打印出来;
               由于直接看int类型的dest是看不到里面的内容的;由于有unsigned char *desc1 = (unsigned char*)desc;所以字符能够传
               到dest里面保存起来,dest所指向的内存长度4个字节,强制转化为char 就是把四个字节分成一个一个的字节,这样就能够看到
               一个个字符了,假设定义成char dest[5] = "1234";就不用转化;呵呵,表达起来真累人;
          (6)memcpy1(dest,src,sizeof(src));注意里面的sizeof(src),这个是包括字符串的结束符'/0'的;所以不用操心printf(dest);
               可是假设用memcpy1(dest,src,4);没有'/0'就要*(dest+5) = '/0';这样保证是一个完整的字符串;
          (7)假设初始化的时候:
 char dest[1024] = "12345666";//{0};
 const char src[5] = "3333";
               那么拷贝的时候,假设用memcpy1(dest,src,sizeof(src));则printf(dest);出来是3333
               假设memcpy1(dest,src,4);则printf(dest);出来是33335666;由于上面的sizeof(src),包括'/0',所以拷贝过去的字符串以'/0'
               结束,就仅仅有3333,而假设传4个字符,'/0'是第五个字符,那就遇到dest[1024] 的'/0'结束,所以是33335666
               字符串的'/0'问题一定要注意啊!!!

实际应用:
unsigned char g_pData[1024] = "";
DWORD g_dwOffset = 0;
bool PackDatatoServer(const unsigned char *pData, const unsigned int uSize)
{
 memcpy(g_pData+g_dwOffset, pData, uSize);
 g_dwOffset += uSize;
 //g_pData += uSize;
 return true;
}

void main()
{
 const unsigned char a[4] = "123";
 PackDatatoServer(a, 3);
 PackDatatoServer(a, 1111);
 int b = -1;
}

PackDatatoServer()函数的作用是把每次的资源内存复制到目标内存里面,并且是累加的拷贝;也就是后一次紧接着上一次的拷贝;
显然用到了memcpy函数;
实现原理是用到了一个全局变量g_dwOffset 保存之前拷贝的长度,最開始没有想到这一点,结果每次拷贝都是一次性的,下一次拷贝把
上一次的冲掉了;所以用全局变量记录拷贝的长度;
第二个须要注意的是,拷贝的过程中注意不要改变目标指针的指向,即目标指针始终指向初始化的时候指向的位置;那么怎么实现累积拷贝呢?
就是用的指针偏移;第一次实现的时候,把g_pData += uSize;写到了函数里面,这样写是可以实现指针位移的目标,可是指针指向也发生改变;
 另外:g_pData += uSize;也有报错:left operand must be l-value,原因是:把地址赋值给一个不可更改的指针!
比方:
  char   a[100];  
  char   *p   =   new   char[10];  
  a   =   p;   //这里出错,注意了:数组的首地址也是一个常量指针,指向固定不能乱改的~~
   
  char   *   const   pp   =   new   char[1];  
  pp   =   a;   //也错  
所以既不能改变首地址,又要满足累积赋值(就是赋值的时候要从赋过值的地方開始向下一个内存块赋值,想到指针加),所以想到把指针加写到
函数參数里面,这时就要充分了解memcpy的实现过程,里面是一个一个字符的赋值的,想连续赋值,就要把指针指向连续的内存的首地址,所以,
真的非常不好表达,呵呵,就这样了,一大推零散的知识。。。

memcpy的使用方法总结的更多相关文章

  1. C++:怎样把一个int转成4个字节?

    大家都知道,一个int 或 unsigned int是由4个字节组成的,(<C/C++学习指南>,第3章,第3.2.3节:变量的内存视图) 比如, int   n  =  sizeof( ...

  2. javaSE27天复习总结

    JAVA学习总结    2 第一天    2 1:计算机概述(了解)    2 (1)计算机    2 (2)计算机硬件    2 (3)计算机软件    2 (4)软件开发(理解)    2 (5) ...

  3. memcpy函数的使用方法

    c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中. 1.函数原型 void *memcpy(void * ...

  4. strcpy、strncpy与memcpy的区别与使用方法

    strcpy.strncpy.memcpy这三个C语言函数我们在主机代码编写中会很频繁的使用到,但是三个函数的区别.使用时该注意什么还是有必要说下的. 本文参考<C 标准库>编写. 一.函 ...

  5. memcpy一种实现方法

    #include<stdio.h> #include<stdlib.h> void* memncpy(void* dest, const void* src, int coun ...

  6. iOS常用系统信息获取方法

    一.手机电量获取,方法二需要导入头文件#import<objc/runtime.h> 方法一.获取电池电量(一般用百分数表示,大家自行处理就好) -(CGFloat)getBatteryQ ...

  7. TaintDroid剖析之Native方法级污点跟踪分析

    1.Native方法的污点传播 在前两篇文章中我们详细分析了TaintDroid对DVM栈帧的修改,以及它是如何在修改之后的栈帧中实现DVM变量级污点跟踪的.现在我们继续分析其第二个粒度的污点跟踪—— ...

  8. linux 内核与用户空间通信之netlink使用方法

    转自:http://blog.csdn.net/haomcu/article/details/7371835 Linux中的进程间通信机制源自于Unix平台上的进程通信机制.Unix的两大分支AT&a ...

  9. bzoj2141排队(辣鸡但是好写的方法)

    题意很明确,也非常经典: 一个支持查询 区间中比k大的数的个数 并且支持单点修改的序列 ——因为题意可以转化为:查询这两个数中比后者大的个数.比后者小的个数.比前者大的个数.比前者小的个数(根据这4个 ...

随机推荐

  1. Swift -- SnapKit

    Snapkit SnapKit是专门为Swift语言提供AutoLayout布局使用的,特点为语法简洁易用. let subview = UIView() subview.backgroundColo ...

  2. 分享关于学习new BufferedWriter()方法时常遇到的一个无厘头的问题

    今天在学习IO的过程中,关于处理流BufferedWriter的使用时,遇到了一个很犯二但是又会让初学者经常没有避免的问题,百度后才发现有人和我一样二,这还是对java基础掌握得不牢固的原因啊. 首先 ...

  3. JNI/NDK开发指南(一)—— JNI开发流程及HelloWorld

    转载请注明出处:http://blog.csdn.net/xyang81/article/details/41777471 JNI全称是Java Native Interface(Java本地接口)单 ...

  4. 将excel数据导入内表的函数

    call function 'TEXT_CONVERT_XLS_TO_SAP'    exporting      i_tab_raw_data       = lt_raw "开始行    ...

  5. Emily姨妈家的猫

    按书上的样例,慢慢理解. 其实,JAVASCRIPT也应该可以写出正规点的,封装性好的代码. <html> <body> <script type="text/ ...

  6. 2016 Web 开发资源工具大搜罗

    原文链接: 100+ Awesome Web Development Tools and Resources Web的迅猛发展对于开发者来说既是一件好事也是一件坏事.不断紧跟潮流学习新的技术.编程语言 ...

  7. Php使用sqlite

    php sqlite文档:http://php.net/manual/en/book.sqlite.php sql:http://www.php100.com/html/webkaifa/PHP/PH ...

  8. Learning WCF Chapter2 Service Contracts

    A service contract describes the operations supported by a service,the message exchange pattern they ...

  9. Method Overloading in WCF zt

    Method overloading is the process of implementing Polymorphism in Object-Oriented Programming. A met ...

  10. POJ 3107

    #include<iostream> #include<cstdio> #include<cstring> #include<string> #incl ...