2

从这个链接: http ://clc-wiki.net/wiki/memmove

#include <stddef.h> /* for size_t */
void *memmove(void *dest, const void *src, size_t n)
{
    unsigned char *pd = dest;
    const unsigned char *ps = src;
    if (__np_anyptrlt(ps, pd))
        for (pd += n, ps += n; n--;)
            *--pd = *--ps;
    else
        while(n--)
            *pd++ = *ps++;
    return dest;
}

使用是__np_anyptrlt多余的吗?为什么不直接使用if (ps < pd)

4

1 回答 1

4

您链接的页面上的注释解释了它:

__np_anyptrlt(p1, p2):

一个宏或函数,对于任何两个指针 p1 和 p2,__np_anyptrlt(p1,p2) 计算为:

  • 如果 p1 和 p2 指向同一个对象并且 p1 小于 p2,则非零
  • 如果 p1 和 p2 指向同一个对象并且 p1 大于 p2,则为零
  • 如果指针未指向同一对象或它们比较相等,则为未指定的整数值。

一个简单的实现是 ((p1) < (p2)),但根据标准 6.5.9(N1124 编号),当 p1 和 p2 不指向内部(或一个成员超过末尾)时,这会导致未定义的行为单个数组对象。这种幼稚的实现只能由可以确保在这些情况下行为始终合理的实现者使用。在这些情况下,表达式的实际最终值并不重要,因为对于不同的对象,无论 memmove 在哪个方向迭代,都不可能破坏内存。

因此,只有ps < pd当您的平台保证指向不同数组的指针之间的比较行为正常时,才可以安全使用。该标准规定此类比较是未定义的,因此无用的编译器可能会创建可以执行任何操作的代码(例如崩溃、破坏数据或让恶魔飞出你的鼻子)。

大多数编译器可能会做一些可以接受的事情,但您需要查阅特定编译器的文档才能确定。

于 2013-11-19T04:11:44.987 回答