2010-06-30 53 views
2

我看了文章Optimizing Memcpy improves speed,我對修改後的GNU算法有疑問,運行代碼時出錯src & 0xFFFFFFFC,src是一個void指針,它可以是左邊的「&」的操作數?我在這裏錯過了什麼嗎?關於修改GNU算法的問題

感謝

錯誤1錯誤C2296:「&」:非法的,左邊的操作數的類型「常量無效*」

void * memcpy(void * dst, void const * src, size_t len) 
{ 
    long * plDst = (long *) dst; 
    long const * plSrc = (long const *) src; 
    if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC)) 
    { 
     while (len >= 4) 
    { 
      *plDst++ = *plSrc++; 
      len -= 4; 
     } 
    } 
    char * pcDst = (char *) plDst; 
    char const * pcSrc = (char const *) plSrc; 
    len += 4; 
    while (len--) 
    { 
     *pcDst++ = *pcSrc++; 
    } 
    return (dst); 
} 
+0

要知道,對於一個在PC機上GCC明白基本* *的memcpy定義不夠好,它就會發出代碼以時間來寫多頭,而雙多頭,如果你告訴它,它可以使用MMX。 – 2010-07-09 07:07:21

回答

1

可以位掩碼指針 - 它是一個合法的操作,如果你知道是什麼你在做。

首先,確保你的編譯器在C++模式下不是而不是(因爲看起來你使用的是MSVC++) - 這應該是C中的警告,而不是錯誤。

其次,0xFFFFFFFC是一個整數 - 您應該對相關操作進行相應的轉換(使其成爲指針類型)。第三,我期望你的編譯器/ libc已經有了一個奇妙的執行memcpy - 使用內置的一個,而不是你自己的版本。編譯器確實對C和標準庫函數執行了一些詭計,甚至可能會內聯和展開memcpy循環。當你製作自己的memcpy時,這個技巧通常不會被完成。

+0

感謝theatrus,我只是想找到一個更有效的方式來使用memcpy進行數據傳輸,我認爲做src&0xFFFFFFFC是沒有意義的。 – Blurmylife 2010-06-30 21:16:40

+0

這個想法是在32位邊界上對齊寫入。 – 2010-07-01 12:39:37

+1

爲了進一步提出這些意見:在32位邊界上對齊的寫操作通常比不寫操作要快得多。寫入對齊的32位塊通常比單獨寫入4個字節要快得多。這一切都取決於處理器,在這裏,我們可能意味着一些基於x86的東西,儘管這對許多(不一定是全部)架構都適用。 – Thanatos 2010-07-09 06:41:11

0

我閱讀 http://www.eetimes.com/design/embedded/4024961/Optimizing-Memcpy-improves-speed/ 類似的文章,這似乎我錯了的部分是

if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC)) 

不檢查對齊指針。

例如,如果src是0x13(奇數),那麼 src & 0xFFFFFFFC是0x10。 !(0x10)是0,所以如果失敗。精細。

如果src對齊,比如說0x14,那麼 src & 0xFFFFFFFC是0x14。 !(0x14)是0,所以如果失敗。哎呀。

我認爲這是適當的檢查:

if (!(src & 0x3) && !(dst & 0x3)) { 
    // pointers are aligned, copy in 32 bit chunks 
    .... 
} 

,我還沒有看到的len宗旨+ = 4; 但我想原來的問題只是關於一個編譯錯誤,所以這整個迴應有點離題,也許我誤解了它應該如何工作。 (我同意原來的答案,只是使用庫中的內容)。

1

不確定這麼長時間沒有答案。 C標準真的不能再清楚這一點C99§6.5.10(按位與運算符):

約束

每個操作數應具有整數類型。

因此,你需要的指向整數它們可以被用來作爲&操作數之前;具體來說,你應該將它們轉換爲intptr_t(或uintptr_t),爲此標準保證「任何有效的void指針都可以轉換爲這種類型,然後轉換回void指針,結果將與原始指針相等「

#include <stdint.h> 
... 
if ((intptr_t)src & 3) { 
    // src does not have 4 byte alignment 
} 

有你的代碼中的一些其他問題,但加入石膏將讓你轉移到尋找那些。