程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> memcpy的兩種實現

memcpy的兩種實現

編輯:關於C語言
 

第一種:最常見的:

void* memcpy( void* dest, const void* src, size_t count )

{

if (count<0)

{printf("Invalid count number !.\n");

return (void*)0;}

if(src==NULL||dest==NULL)

return (void*)0 ;

if ((unsigned int)dest==(unsigned int)src)

{printf("The source is equal with the destanation!.\n");

return dest;}

char* d = (char*)dest;

const char* s = (const char*)src;

while(count--)

*d++ = *s++;

return dest;

}

另一個實現,和上面類似,轉貼高質量C++/C編程指南中的,供參考:

void *memcpy(void *pvTo, const void *pvFrom, size_t size)

{

assert((pvTo != NULL) && (pvFrom != NULL)); // 使用斷言

byte *pbTo = (byte *) pvTo; // 防止改變pvTo的地址

byte *pbFrom = (byte *) pvFrom; // 防止改變pvFrom的地址

while(size -- > 0 )

*pbTo ++ = *pbFrom ++ ;

return pvTo;

}

第二種:轉自變態之MEMCPY

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

switch( count & 7 )

{

case 0: 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++;

} while (--n > 0);

}

return dest;

}

解釋:摘自原貼:

int n = (count + 7) / 8;計算要復制的輪數(每輪復制8位),剩下的余數位數也要復制進去。

count & 7控制要復制余數位數,while (--n > 0)控制輪數。

比如count = 9,則n = 2,count & 7 = 1,要復制2輪,程序跳到case1執行,復制一位之後,再循環一輪,復制8位.

為何這麼實現:引用上面帖子後面的評論:

每8個字節拷貝省7個跳轉(AMD處理器內部分支預測算法是“假定全都跳轉”,因此這裡也就是相當於省了7個時鐘周期);把swith和do循環湊到一起,多少省幾個字節的空間……

但使用32位或64位指令,可以得到更大的優化效果,代碼還要精煉得多。

說實在話:除非內存小到極點、並且無法增加的系統,寫出這樣的程序純屬作孽……

後記:一般出題目讓你實現memcpy,個人理解,其意圖至少有以下幾點:

1.寫任何程序都能反映出你的代碼風格.

2.考查你是否注意到,要拷貝的源,即const void* src,應該是用const的,避免有意或無意的修改.

3.考查你,不應該直接對src和dst指針進行類似++或--之類的操作,而應該另外申請對應變量用於此操作.

4.指針的類型轉化問題,原始參數應該是void *的,你具體操作的時候,應該是轉化為某種具體的類型,此處用char比較適合.

5.注意要判斷源src是否和dest重復,如果重復,直接返回或返回錯誤.

6.應該還有其他考慮,如果以後想到,再補充.

補充:後來又重新看了高質量C++/C編程指南,其中,原作者直接對const char *strSrc和strDest進行++操作

char *strcpy(char *strDest, const char *strSrc);

{

assert((strDest!=NULL) && (strSrc !=NULL)); // 2分

char *address = strDest; // 2分

while( (*strDest++ = * strSrc++) != ‘\0’ ) // 2分

NULL ;

return address ; // 2分

}

此時我才注意到,自己總結的上面第三點,是錯誤的,因為const char *strSrc中的const是指字符串內容為const,而不是說strSrc是const的,如果要指定strSrc是const,應該寫成 char * const strSrc 。

不過,對此,有人也許又該問了,那此處對strSrc進行++操作,不是破壞了原先strSrc的指向了嗎?

如果你真是這麼問,那麼說明你的概念還不是很清楚(我開始也是和你犯了同樣錯誤),實際上這點在高質量C++/C編程指南,也有提及,因為strSrc是函數的形參,而此處雖然對形參的進行++ 操作,改變其指向,但是並沒有改變原始屬性為const的字符串,而且此處的形參,在函數調用結束之後,也就釋放了,對原始傳來的地址,沒有任何影響。

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved