以前没注意过多字节赋值问题,考虑的角度是充分利用 cpu 的 32 位带宽。一次复制 1 个字节和一次复制 4 个字节占用的 cpu 指令周期是一样的,既然我们的 cpu 能同时操作 32 位,为什么我们不能一次复制 4 个字节呢?如此一来,总运行的指令数将降低到原来的 1/4 !
于是有下面代码:
1 void *memcpy(void *dest, void *src, size_t count)
2 {
3 size_t c = count >> 2; /* 相当于 count / 4 */
4 long *pt;
5 const long *ps;
6 if (c)
7 {
8 /* 首先按 4 个字节复制 */
9 pt = (long *) dest;
10 ps = (const long *) src;
11 while (c)
12 {
13 *pt = *ps;
14 pt++;
15 ps++;
16 c--;
17 }
18 }
19 c = count & 3; /* 得到 count 模 4 的余数 */
20 if (c)
21 {
22 /* 如果有剩下的,再按 1 个字节复制剩余的 */
23 char *pct = (char *) pt;
24 const char *pcs = (const char *) ps;
25 while (c)
26 {
27 *pct = *pcs;
28 pct++;
29 pcs++;
30 c--;
31 }
32 }
33 return dest;
34 }
通过使用 long 型指针,强行按 4 个字节复制。
还有对 3 种 memcpy 实现的对比,上述算法受到地址对齐的影响较为严重。在地址按4 字节对齐的时候,上述算法的效率比单字节 memcpy 实现高很多,但如果地址没有按4 字节对齐,则其效率并不高,有时甚至还比普通 memcpy 还低。这可能是因为,虽然上述算法减少了 cpu 的指令数,但内存的速度比 cpu 慢得多,速度的瓶颈还是在内存。
编辑特别推荐: