理解memcpy()的源代码

Ang*_*gus 20 c

00018 void *memcpy(void *dst, const void *src, size_t len)
00019 {
00020         size_t i;
00021 
00022         /*
00023          * memcpy does not support overlapping buffers, so always do it
00024          * forwards. (Don't change this without adjusting memmove.)
00025          *
00026          * For speedy copying, optimize the common case where both pointers
00027          * and the length are word-aligned, and copy word-at-a-time instead
00028          * of byte-at-a-time. Otherwise, copy by bytes.
00029          *
00030          * The alignment logic below should be portable. We rely on
00031          * the compiler to be reasonably intelligent about optimizing
00032          * the divides and modulos out. Fortunately, it is.
00033          */
00034 
00035         if ((uintptr_t)dst % sizeof(long) == 0 &&
00036             (uintptr_t)src % sizeof(long) == 0 &&
00037             len % sizeof(long) == 0) {
00038 
00039                 long *d = dst;
00040                 const long *s = src;
00041 
00042                 for (i=0; i<len/sizeof(long); i++) {
00043                         d[i] = s[i];
00044                 }
00045         }
00046         else {
00047                 char *d = dst;
00048                 const char *s = src;
00049 
00050                 for (i=0; i<len; i++) {
00051                         d[i] = s[i];
00052                 }
00053         }
00054 
00055         return dst;
00056 }
Run Code Online (Sandbox Code Playgroud)

我刚刚完成了一个实现memcpy,以了解它与使用循环的不同之处.但我看不出使用循环而不是memcpymemcpy内部再次使用循环来复制之间的任何区别.

我无法理解if他们为整数做的部分 - i < len/sizeof(long).为什么需要这个计算?

And*_*ter 15

我无法理解他们是否为整数所做的部分.我<len/sizeof(长).为什么需要这个计算?

因为它们是复制单词,而不是单个字节,在这种情况下(正如评论所说,它是一种优化 - 它需要更少的迭代,CPU可以更有效地处理字对齐的数据).

len是要复制的字节数,并且sizeof(long)单个字大小,因此要复制的元素数(表示要执行的循环迭代)是len / sizeof(long).

  • 可能应该在我的回答中说“架构”而不是“CPU”,就像您所做的那样:) (2认同)

m0s*_*it0 6

了解它与使用循环的不同之处.但是我使用循环而不是memcpy没有任何区别,因为memcpy在内部再次使用循环来复制

那么它使用循环.也许libc的其他实现不会那样做.无论如何,如果它确实使用了循环,那么问题/问题是什么?另外,正如您所看到的那样,它不仅仅是一个循环:它会检查对齐并根据对齐方式执行不同类型的循环.

我无法理解他们是否为整数所做的部分.我<len/sizeof(长).为什么需要这个计算?

这是检查内存字对齐.如果目标和源地址是字对齐的,并且长度副本是字大小的倍数,那么它通过word(long)执行对齐的副本,这比使用bytes(char)更快,这不仅仅是因为大小,而是也因为大多数架构都能更快地进行字对齐复制.


hus*_*sik 5

len%sizeof(long)检查您是否尝试复制不属于的完整长度long

00035    if ((uintptr_t)dst % sizeof(long) == 0 &&
00036             (uintptr_t)src % sizeof(long) == 0 &&
00037             len % sizeof(long) == 0) {
00038 
00039                 long *d = dst;
00040                 const long *s = src;
00041 
00042                 for (i=0; i<len/sizeof(long); i++) {
00043                         d[i] = s[i];
00044                 }
Run Code Online (Sandbox Code Playgroud)

检查是否对齐,如果为true,则快速复制(sizeof(long)一次复制一个字节)。

00046    else {
00047                 char *d = dst;
00048                 const char *s = src;
00049 
00050                 for (i=0; i<len; i++) {
00051                         d[i] = s[i];
00052                 }
00053    }
Run Code Online (Sandbox Code Playgroud)

这是用于未对齐的数组(慢速复制(一次1字节))