开发者

Question about The modified-GNU algorithm

I read the article Optimizing Memcpy improves speed, I have a question about the modified-GNU algorithm, I get an error running the code the src & 0xFFFFFFFC , src is a void pointer, can it be a left operand for ‘&’ ? Did I miss anything here?

Thanks

Error 1 error C2296: '&' : illegal, left operand has type 'const void *’

void * memcpy(void * dst, void const * src, size_t len)
{
    long * plDs开发者_运维问答t = (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);
}


You can bitmask pointers - it is a legitimate operation if you know what you are doing.

First off, make sure your compiler is not in C++ mode (since it appears you are using MSVC++) - this should be a warning in C, not an error.

Second, 0xFFFFFFFC is an integer - you should make the appropriate cast for the operation in question (make it a pointer type).

Third, I would expect your compiler/libc already has a fantastic implementation of memcpy - use the built in one, not your own version. Compilers do perform some trickery with C and standard library functions, and may even inline and unroll memcpy loops. When you make your own memcpy, this trickery is usually not done.


Not sure how this went unanswered for so long. The C standard really couldn't be clearer on this point C99 §6.5.10 (Bitwise AND operator):

Constraints

Each of the operands shall have integer type.

Thus, you need to cast the pointers to integers before they can be used as operands of &; specifically, you should cast them to intptr_t (or uintptr_t), for which the standard guarantees "that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer"

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

There are some other issues with your code, but adding the casts will let you move on to finding those.


I read a similar article at http://www.eetimes.com/design/embedded/4024961/Optimizing-Memcpy-improves-speed/ and the part that seems wrong to me is that

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

does not check for aligned pointers.

for example, if src is 0x13 (odd), then src & 0xFFFFFFFC is 0x10. !(0x10) is 0, so the if fails. fine.

if src is aligned, say 0x14, then src & 0xFFFFFFFC is 0x14. !(0x14) is 0, so the if fails. oops.

I would think this is the appropriate check:

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

and I also don't see the purpose in len += 4; but i guess the original question was just about a compile error, so this whole response is somewhat a digression, and maybe i've misunderstood how it is supposed to work. (and I agree with the original answer, just use what comes in the library).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜