在memmove中使用__np_anyptrlt?

时间:2013-11-19 03:46:42

标签: c memmove

从这个链接: 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)

1 个答案:

答案 0 :(得分:3)

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

  

__ np_anyptrlt(p1,p2):

     

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

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

一个天真的实现是((p1)&lt;(p2)),但是根据标准,6.5.9(N1124编号),当p1和p2没有指向(或者一个成员过去)时,这会导致未定义的行为一个数组对象的结束。这种天真的实现只应由实现者使用,这些实现者可以确保在这些情况下行为总是合理的。在这些情况下,表达式的实际结束值无关紧要,因为对于不同的对象,无论memmove在哪个方向迭代,都不可能破坏内存。

因此,如果您的平台保证指向不同数组的指针之间的比较表现良好,那么使用ps < pd是唯一安全的。标准说这种比较是未定义的,所以一个无益的编译器可能会创建任何可以执行任何操作的代码(例如崩溃,破坏数据或让恶魔飞出你的鼻子)。

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