了解memcpy()的实现 [英] Understanding the implementation of memcpy()

查看:394
本文介绍了了解memcpy()的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在寻找memcpy.c的实现,发现了另一个memcpy代码.我不明白为什么他们要这样做(((ADDRESS)s)|((ADDRESS)d)| c)& (sizeof(UINT)-1)

I was looking the implementation of memcpy.c, I found a different memcpy code. I couldnt understand why do they do (((ADDRESS) s) | ((ADDRESS) d) | c) & (sizeof(UINT) - 1)

#if !defined(__MACHDEP_MEMFUNC)

#ifdef _MSC_VER
#pragma function(memcpy)
#undef __MEMFUNC_ARE_INLINED
#endif

#if !defined(__MEMFUNC_ARE_INLINED)
/* Copy C bytes from S to D.
 * Only works if non-overlapping, or if D < S.
 */
EXTERN_C void * __cdecl memcpy(void *d, const void *s, size_t c)
{
    if ((((ADDRESS) s) | ((ADDRESS) d) | c) & (sizeof(UINT) - 1)) {

        BYTE *pS = (BYTE *) s;
        BYTE *pD = (BYTE *) d;
        BYTE *pE = (BYTE *) (((ADDRESS) s) + c);

        while (pS != pE)
            *(pD++) = *(pS++);
    }
    else {
        UINT *pS = (UINT *) s;
        UINT *pD = (UINT *) d;
        UINT *pE = (UINT *) (BYTE *) (((ADDRESS) s) + c);

        while (pS != pE)
            *(pD++) = *(pS++);
    }
    return d;
}

#endif /* ! __MEMFUNC_ARE_INLINED */
#endif /* ! __MACHDEP_MEMFUNC */

推荐答案

代码正在测试地址是否适合UINT对齐.如果是这样,代码将使用UINT对象进行复制.如果不是,则代码使用BYTE对象进行复制.

The code is testing whether the addresses are aligned suitably for a UINT. If so, the code copies using UINT objects. If not, the code copies using BYTE objects.

该测试通过首先对两个地址进行按位或运算来工作.任何一个地址中打开的任何位都将在结果中打开.然后,测试对sizeof(UINT) - 1执行按位与运算.预期UINT的大小是2的幂.然后,大小减一将所有低位都打开.例如,如果大小为4或8,则比二进制11 2 或111 2 小.如果其中一个地址不是UINT的大小的倍数,则它将打开这些位之一,测试将对其进行指示. (通常,整数对象的最佳对齐方式与其大小相同.这不一定是正确的.此代码的现代实现应使用_Alignof(UINT) - 1而不是大小.)

The test works by first performing a bitwise OR of the two addresses. Any bit that is on in either address will be on in the result. Then the test performs a bitwise AND with sizeof(UINT) - 1. It is expected the the size of a UINT is some power of two. Then the size minus one has all lower bits on. E.g., if the size is 4 or 8, then one less than that is, in binary 112 or 1112. If either address is not a multiple of the size of a UINT, then it will have one of these bits on, and the test will indicate it. (Usually, the best alignment for an integer object is the same as its size. This is not necessarily true. A modern implementation of this code should use _Alignof(UINT) - 1 instead of the size.)

使用UINT对象进行复制的速度更快,因为在硬件级别上,一条加载或存储指令会加载或存储UINT的所有字节(可能为四个字节).使用这些指令时,处理器的复制速度通常比使用四倍的单字节加载或存储指令时要快.

Copying with UINT objects is faster, because, at the hardware level, one load or store instruction loads or stores all the bytes of a UINT (likely four bytes). Processors will typically copy faster when using these instructions than when using four times as many single-byte load or store instructions.

此代码当然取决于实现;它需要不属于基本C标准的C实现的支持,并且取决于它所执行的处理器的特定功能.

This code is of course implementation dependent; it requires support from the C implementation that is not part of the base C standard, and it depends on specific features of the processor it executes on.

更高级的memcpy实现可能包含其他功能,例如:

A more advanced memcpy implementation could contain additional features, such as:

  • 如果其中一个地址是对齐的,但另一个地址未对齐,请使用特殊的不对齐加载指令从一个地址加载多个字节,并将常规存储指令加载到另一个地址.
  • 如果处理器具有单指令多数据指令,请使用这些指令在一条指令中加载或存储许多字节(通常为16个,可能更多).

这篇关于了解memcpy()的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆