strcmp/strncmp源码分析

来源:互联网 发布:单片机常用芯片 编辑:程序博客网 时间:2024/05/20 18:45

1. strcmp

  strcmp 用于比较两个字符串是否相等。内部实现与我们最初的想法一致,就是循环遍历两个字符串,遇到不相等的那一位即返回差值。

intstrcmp (p1, p2)     const char *p1;     const char *p2;{  register const unsigned char *s1 = (const unsigned char *) p1;  register const unsigned char *s2 = (const unsigned char *) p2;  unsigned char c1, c2;  do    {      c1 = (unsigned char) *s1++;      c2 = (unsigned char) *s2++;      if (c1 == '\0')return c1 - c2;    }  while (c1 == c2);  return c1 - c2;}
  这里用到了 register 修饰符。register 修饰符意思是将此变量的值存放到寄存器中。除此之外,也没做别的特殊优化。


2. strncmp

  此函数功能与 strcmp 类似,也是比较两个字符串的大小,不同的是只比较前 n 个字符,相对于之前的版本来说更加安全。

  对于此函数,最简单的想法就是按字符逐个比较,直到遇到字符串结束。

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

  以下是 strncmp 的 glibc 的实现。

/* Compare no more than N characters of S1 and S2,   returning less than, equal to or greater than zero   if S1 is lexicographically less than, equal to or   greater than S2.  */intstrncmp (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;}

  算法的重点在那个大大的 “do” 循环里面。明明一个小循环就能搞定的,为什么要把同样的四行代码 copy 四遍呢?

  这应该与CPU处理器进行流水线操作时的分支预测有关系,这么做可以让其每四次才经历一次分支预测。下表是两个函数分别运行 10w 次的运行结果。


表1: strncmp 与 my_strncmp 效率对比字符串长度strncmp 运行时间(ms)my_strncmp 运行时间(ms)52.623.10208.1710.9810038.7045.3620075.5588.62

  从上表可以看出,对于预测流水线的优化有一定效果,但是优化效果在10%~20%左右。

原创粉丝点击