2011-03-15 101 views
5

可以吗?memcpy部分复制

char buf[] = { 0, 1, 2 }; 
memcpy(buf, buf + 1, 2); 

是否有更大的数据类型有什么区别?我知道我可以使用memmove(),但我只是好奇。

+0

-1:当你尝试时发生了什么? – pmg 2011-03-15 12:03:17

+3

+1,因为我不同意pmg的-1。 “当你在标准中查看时发生了什么?”,也许,但是在尝试这种事情时存在真正的风险,你可能会尝试并且“有效”,结果为{1,2,2} '在缓冲区中。那么建议有什么用处呢?它是否会在下周仍然有效,或者当您打开优化或客户计算机时仍然有效? – 2011-03-15 12:37:49

+0

@Steve Jessop:我同意。 OP的例子将(可能)工作,这取决于'memcpy'的特定目标平台实现,但这并不是一个好主意! – GrahamS 2011-03-15 12:42:00

回答

12

当输入和输出重叠时,memcpy的效果未定义。你应该使用memmove

5

不好。当源和目标重叠时,您必须必须使用memmove

可能使用memcpy,这取决于你的编译器的实现,但这不是你应该依赖的东西!


一个典型的幼稚的做法是逐字节副本(UINT8)是这样的:

typedef unsigned char uint8; 

void * memcpy (void * destination, const void * source, size_t num) 
{ 
    const uint8* pSrc = (const uint8*)source; 
    const uint8* const pSrcEnd = pSrc + num; 
    uint8* pDst = (uint8*)destination; 

    while (pSrc != pSrcEnd) 
     *(pDst++) = *(pSrc++); 

    return destination; 
} 

这将工作没关系你memcpy(buf, buf + 1, 2),但少为人与memcpy(buf + 1, buf, 2)

3

如果内存区域重叠,行为是不确定的,所以这是不好的。

1

这是不确定的行为,但我已经用它像这样,

char buf[] = {0, 1, 2, 3); 
memcpy(buf, buf+2, 2); 

在目的地的终点是小于源的起点。 你应该仍然使用memmove来确保...

+0

GNU C库已经转换了几次memcpy的实现。有时甚至i686与i386与x86_64不同。 – 2012-04-11 22:19:28