关于修改后的GNU算法的问题

时间:2010-06-30 16:17:27

标签: c optimization

我阅读了文章Optimizing Memcpy improves speed,我对修改后的GNU算法有疑问,运行代码src& 0xFFFFFFFC,src是一个void指针,它可以是'&'的左操作数吗?我在这里错过了什么吗?

由于

错误1错误C2296:'&' :非法,左操作数的类型为'const void *'

void * memcpy(void * dst, void const * src, size_t len)
{
    long * plDst = (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);
}

3 个答案:

答案 0 :(得分:1)

你可以使用bitmask指针 - 如果你知道自己在做什么,这是一个合法的操作。

首先,确保您的编译器在C ++模式下(因为看起来您使用的是MSVC ++) - 这应该是C中的警告,而不是错误。

其次,0xFFFFFFFC是一个整数 - 您应该对相关操作进行适当的转换(使其成为指针类型)。

第三,我希望你的编译器/ libc已经有了memcpy的精彩实现 - 使用内置的,而不是你自己的版本。编译器确实使用C和标准库函数执行一些技巧,甚至可以内联和展开memcpy循环。当你制作自己的memcpy时,通常不会这样做。

答案 1 :(得分:1)

不知道这长久以来如何得不到答案。在这一点C99§6.5.10(按位AND运算符)中,C标准真的不能更清楚:

  

<强>约束

     

每个操作数都应具有整数类型。

因此,在将它们用作&的操作数之前,您需要转换指向整数的指针;具体来说,你应该将它们转换为intptr_t(或uintptr_t),标准保证“任何有效的void指针都可以转换为此类型,然后转换回指向void的指针,并且结果将等于原始指针“

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

您的代码还存在其他一些问题,但添加演员表会让您继续寻找代码。

答案 2 :(得分:0)

我在阅读类似的文章 http://www.eetimes.com/design/embedded/4024961/Optimizing-Memcpy-improves-speed/ 而对我来说似乎不对的部分就是那个

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

不会检查对齐的指针。

例如,如果src是0x13(奇数),那么 src&amp; 0xFFFFFFFC是0x10。 !(0x10)为0,因此if失败。细

如果src对齐,比如说0x14,那么 src&amp; 0xFFFFFFFC是0x14。 !(0x14)为0,因此if失败。糟糕。

我认为这是适当的检查:

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

我也没有看到len + = 4的目的; 但我想原来的问题只是一个编译错误,所以这整个回应有点偏离,也许我误解了它应该如何工作。 (我同意原始答案,只使用库中的内容)。