我阅读了文章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);
}
答案 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的目的; 但我想原来的问题只是一个编译错误,所以这整个回应有点偏离,也许我误解了它应该如何工作。 (我同意原始答案,只使用库中的内容)。