【问题标题】:memcpy copying partly over itselfmemcpy 部分复制自身
【发布时间】:2011-03-15 11:59:34
【问题描述】:

这样好吗?

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

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

【问题讨论】:

  • -1:你尝试的时候发生了什么?
  • +1,因为我不同意pmg的-1。 “当你在标准中查找它时发生了什么?”,也许,但在试验这种东西时存在真正的风险,你可能会尝试它并且它“有效”,结果{1,2,2}在缓冲区中。那么尝试它的建议有什么用呢?下周,或者当您开启优化,或在您客户的计算机上,它是否仍然有效?
  • @Steve Jessop:我同意。 OP 的示例(可能)会起作用,具体取决于 memcpy 的特定目标平台实现,但这并不是一个好主意!
  • 事情是:他说 “我知道我可以使用 memmove()” 并且他仍然问memcpy() 是否可以。他怎么知道他可以使用 memmove 和 NOT KNOW 不能对重叠对象使用 memcpy?
  • @pmg:我想我有点不清楚。我不知何故未能找到明确的答案,因为它是未定义的行为,但显然没有在代码中留下这样的东西。我出于好奇尝试了它,在这种特殊情况下它适用于我的编译器。

标签: c memcpy


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    不好。当源和目标重叠时,您必须使用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】:

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

      【讨论】:

        【解决方案4】:

        这是未定义的行为,但我已经这样使用了,

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

        目标的终点小于源的起点。 您仍然应该使用 memmove 以确保...

        【讨论】:

        • GNU C 库已经多次切换 memcpy 的实现。有时,i686、i386 和 x86_64 甚至会有所不同。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        相关资源
        最近更新 更多