`memcpy` 是記憶體複製的基石,**不處理重疊、極致效能**。本文提供標準實現、字長級優化、編譯器內建利用、嚴格別名規則合規性分析。
#include#include void *my_memcpy(void *dest, const void *src, size_t count) { assert(dest && src); char *d = (char *)dest; const char *s = (const char *)src; void *ret = dest; while (count--) { *d++ = *s++; } return ret; }
int main() {
float src[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
float dst[10] = {0};
size_t bytes = sizeof(src); // 9 * 4 = 36 bytes
my_memcpy(dst, src, bytes);
for (int i = 0; i < 9; i++) {
printf("%.1f ", dst[i]);
}
printf("\n");
return 0;
}
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
void *my_memcpy_fast(void *dest, const void *src, size_t count) {
char *d = (char *)dest;
const char *s = (const char *)src;
void *ret = dest;
// 1. 位址對齊:先複製字節直到 dest 對齊到 sizeof(size_t)
while (count && ((uintptr_t)d % sizeof(size_t))) {
*d++ = *s++;
count--;
}
// 2. 字長級複製 (size_t 通常 8 位元組)
size_t *wd = (size_t *)d;
const size_t *ws = (const size_t *)s;
while (count >= sizeof(size_t)) {
*wd++ = *ws++;
count -= sizeof(size_t);
}
// 3. 餘數字節
d = (char *)wd;
s = (const char *)ws;
while (count--) *d++ = *s++;
return ret;
}
// 現代編譯器 -O2/-O3 會自動向量化簡單迴圈
// 關鍵:使用 restrict 關鍵字 (C99) 告知編譯器無別名
void *my_memcpy_restrict(void *restrict dest, const void *restrict src, size_t n) {
return memcpy(dest, src, n); // 直接呼叫 libc 優化版
}
// 或使用編譯器內建
void *my_memcpy_builtin(void *dest, const void *src, size_t n) {
return __builtin_memcpy(dest, src, n);
}
| 錯誤 | 後果 | 修正 |
|---|---|---|
| 用 int 計數 | 64 位系統 >2GB 複製截斷 | 嚴格用 size_t |
| 忘記返回 dest | 無法鏈式調用 | 保存並返回原 dest |
| 用於重疊區域 | UB,資料損壞 | 重疊用 memmove |
| float* 直接賦值複製 | 違反嚴格別名規則 (UB) | 必須轉 char* 或用 memcpy |
`memcpy` = **字節級語義 + 字長級實現 + 向量化優化**。核心合法性來自 `char*` 的別名特權。現代開發**直接使用標準庫 `memcpy`**,編譯器內建 + libc (glibc/musl/msvcrt) 提供針對目標架構深度優化的實現 (SSE/AVX/NEON/SVE、非暫存寫入、預取、頁面對齊處理)。手寫版本僅供教學理解「字長級複製、對齊處理、餘數處理」三階段邏輯。