strncmp的实现

3
为了磨练我的C技能,我下载了eglibc源代码,发现了strncpy函数。我不明白为什么他要区分n≤4的情况并进行4次测试。
int
STRNCMP (const char *s1, const char *s2, size_t n)
{
  unsigned char c1 = '\0';
  unsigned char c2 = '\0';

  if (n >= 4)
    {
      size_t n4 = n >> 2;
      do
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
        return c1 - c2;
    } while (--n4 > 0);
      n &= 3;
    }

  while (n > 0)
    {
      c1 = (unsigned char) *s1++;
      c2 = (unsigned char) *s2++;
      if (c1 == '\0' || c1 != c2)
    return c1 - c2;
      n--;
    }

  return c1 - c2;
}

也许与内存布局有关,我不确定,请指教。

6
看起来像是循环展开:https://zh.wikipedia.org/wiki/%E5%BE%AA%E7%8E%AF%E5%B1%95%E5%BC%80 - Steve Summit
@SteveSummit 非常感谢您提供的信息。 - Baroudi Safwen
再进一步,你就能拥有邓夫设备了... - wildplasser
1个回答

6
这是一个展开循环。虽然会使二进制文件变大,但它通过消除每4个字节比较中的3次减少、3个分支和3个条件语句来加速字符串比较。
甚至可以通过使用与Duff's device相同的技术进一步优化,但不清楚是否会更快。从链接页面中可以看到,
自动处理余数的方法可能不是所有系统和编译器的最佳解决方案 - 在某些情况下,两个循环实际上可能更快(一个展开的循环用于执行主要复制操作,第二个循环用于处理余数)。问题似乎归结为编译器正确优化设备的能力;它还可能干扰一些体系结构上的流水线和分支预测。当从XFree86 Server 4.0版本中删除大量Duff's device实例时,性能有所提高,可执行文件大小也明显减小。因此,在考虑使用此代码时,值得运行一些基准测试以验证它是否真的是目标架构上、目标优化级别上、目标编译器上最快的代码。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接