溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

memcpy函數(shù)怎么用

發(fā)布時間:2021-12-14 16:02:05 來源:億速云 閱讀:150 作者:小新 欄目:互聯(lián)網(wǎng)科技

小編給大家分享一下memcpy函數(shù)怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

memcpy的用法總結

1、memcpy 函數(shù)用于 把資源內(nèi)存(src所指向的內(nèi)存區(qū)域) 拷貝到目標內(nèi)存(dest所指向的內(nèi)存區(qū)域);拷貝多少個?有一個size變量控制
拷貝的字節(jié)數(shù);
函數(shù)原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:(1)可以拷貝任何類型的對象,因為函數(shù)的參數(shù)類型是void*(未定義類型指針),也就是說傳進去的實參可以是int*,short*,char*等等,
但是由于函數(shù)拷貝的過程是一個字節(jié)一個字節(jié)的拷貝的,所以實際操作的時候要把void*強制轉(zhuǎn)化為char*,這樣在指針加的時候才會保證每次加一個字節(jié),呵呵
函數(shù)源代碼實現(xiàn):
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為空的話肯定不能拷貝內(nèi)存空間,src為空相當于沒有拷貝;所以之間return掉;
          (3)""空串是指內(nèi)容為0,NULL是0,不是串;兩個不等價;
          (4)int dest[2] = {0};這是對int 類型的數(shù)組初始化的方法;如果是char類型,就用char a[5] = "1234";  注意數(shù)組下標要
               多于實際看到的字符數(shù),因為還有'/0'
          (5)printf((char *)dest);這句話,是把 char 類型 src 傳到 int 類型的 dest的內(nèi)存強制轉(zhuǎn)化成char類型,然后打印出來;
               因為直接看int類型的dest是看不到里面的內(nèi)容的;因為有unsigned char *desc1 = (unsigned char*)desc;所以字符可以傳
               到dest里面保存起來,dest所指向的內(nèi)存長度4個字節(jié),強制轉(zhuǎn)化為char 就是把四個字節(jié)分成一個一個的字節(jié),這樣就可以看到
               一個個字符了,如果定義成char dest[5] = "1234";就不用轉(zhuǎn)化;呵呵,表達起來真累人;
          (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()函數(shù)的作用是把每次的資源內(nèi)存拷貝到目標內(nèi)存里面,而且是累加的拷貝;也就是后一次緊接著上一次的拷貝;
顯然用到了memcpy函數(shù);
實現(xiàn)原理是用到了一個全局變量g_dwOffset 保存之前拷貝的長度,最開始沒有想到這一點,結果每次拷貝都是一次性的,下一次拷貝把
上一次的沖掉了;所以用全局變量記錄拷貝的長度;
第二個需要注意的是,拷貝的過程中注意不要改變目標指針的指向,即目標指針始終指向初始化的時候指向的位置;那么怎么實現(xiàn)累積拷貝呢?
就是用的指針偏移;第一次實現(xiàn)的時候,把g_pData += uSize;寫到了函數(shù)里面,這樣寫是能夠?qū)崿F(xiàn)指針位移的目標,但是指針指向也發(fā)生改變;
 另外:g_pData += uSize;也有報錯:left operand must be l-value,原因是:把地址賦值給一個不可更改的指針!
比如:
  char   a[100];  
  char   *p   =   new   char[10];  
  a   =   p;   //這里出錯,注意了:數(shù)組的首地址也是一個常量指針,指向固定不能亂改的~~
   
  char   *   const   pp   =   new   char[1];  
  pp   =   a;   //也錯  
所以既不能改變首地址,又要滿足累積賦值(就是賦值的時候要從賦過值的地方開始向下一個內(nèi)存塊賦值,想到指針加),所以想到把指針加寫到
函數(shù)參數(shù)里面,這時就要充分了解memcpy的實現(xiàn)過程,里面是一個一個字符的賦值的,想連續(xù)賦值,就要把指針指向連續(xù)的內(nèi)存的首地址。

以上是“memcpy函數(shù)怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI