右移位和除以2之间的差异(size_t)

时间:2013-11-24 12:37:19

标签: c

这是从Linux内核3.12.1获取的二进制搜索算法。由于size_t总是>=0,我想知道为什么我们不将/2替换为>>

/**
 * @key: pointer to item being searched for
 * @base: pointer to first element to search
 * @num: number of elements
 * @size: size of each element
 * @cmp: pointer to comparison function
 */
void *bsearch(const void *key, const void *base, size_t num, size_t size,
        int (*cmp)(const void *key, const void *elt))
{
    size_t start = 0, end = num;
    int result;

    while (start < end)
    {
        size_t mid = start + (end - start) / 2;

        result = cmp(key, base + mid * size);
        if (result < 0)
            end = mid;
        else if (result > 0)
            start = mid + 1;
        else
            return (void *) base + mid * size;
    }
    return NULL;
}

2 个答案:

答案 0 :(得分:3)

因为那是过早的优化 - 而且很可能编译器足够聪明地实现并且会将除法改为两个右移。

答案 1 :(得分:1)

您只需要提供它没有的编译器信息。编译器已经知道size_t是无符号类型,因此它可以编译/ 2,就像它已经是>> 1一样。任何现代编译器都会进行这种转换。

有时,程序员拥有编译器没有的信息。它可以是这样的:

/* requires y to be larger than x */
int f(int x, int y) {
  int z = y - x;
  return z / 2;
}

在上面的函数中,编译器不能将除法转换为简单的移位(尽管它可以将其转换为使用移位的较长序列并避免除法)。在这种情况下,您可以考虑撰写>> 1而不是/ 2。但是,当从程序中简单地推断出信息时,让编译器推断它。如果您注意到,在阅读生成的程序集时(您应该这样做:它可以让您省去问这个问题的麻烦),考虑到易于获得的信息生成次优代码,提交改进请求编译器的开发人员,而不是使源代码的可读性降低。