c标准库源代码之 strncpy/strncat/strncmp

/* 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. */ int STRNCMP (const char *s1, const char *s2, size_t n) { unsigned reg_char c1 = '/0'; unsigned reg_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; }

char * STRNCPY (char *s1, const char *s2, size_t n) { reg_char c; char *s = s1; --s1; if (n >= 4) { size_t n4 = n >> 2; for (;;) { c = *s2++; *++s1 = c; if (c == '/0') break; c = *s2++; *++s1 = c; if (c == '/0') break; c = *s2++; *++s1 = c; if (c == '/0') break; c = *s2++; *++s1 = c; if (c == '/0') break; if (--n4 == 0) goto last_chars; } n = n - (s1 - s) - 1; if (n == 0) return s; goto zero_fill; } last_chars: n &= 3; if (n == 0) return s; do { c = *s2++; *++s1 = c; if (--n == 0) return s; } while (c != '/0'); zero_fill: do *++s1 = '/0'; while (--n > 0); return s; }

char * strncat (s1, s2, n) char *s1; const char *s2; size_t n; { reg_char c; char *s = s1; /* Find the end of S1. */ do c = *s1++; while (c != '/0'); /* Make S1 point before next character, so we can increment it while memory is read (wins on pipelined cpus). */ s1 -= 2; if (n >= 4) { size_t n4 = n >> 2; do { c = *s2++; *++s1 = c; if (c == '/0') return s; c = *s2++; *++s1 = c; if (c == '/0') return s; c = *s2++; *++s1 = c; if (c == '/0') return s; c = *s2++; *++s1 = c; if (c == '/0') return s; } while (--n4 > 0); n &= 3; } while (n > 0) { c = *s2++; *++s1 = c; if (c == '/0') return s; n--; } if (c != '/0') *++s1 = '/0'; return s; }

 

一般我们会用一个循环来做

但是标准库作者却重复代码,看起来很麻烦,

但是麻烦的带来的好处是速度的提升:

我们在正常的完全循环中每进行一个字符的操作,就会进行一次循环条件的减法和判断

为了减少这些操作,就重复代码,以空间换时间,这是值得的,因为基础函数的使用频度太大了

那位什么重复次数是 4 呢?

首先为了使用高效的移位而不是除法,这个数字不能是奇数

4Bytes对应32bits,编译器一般还都是32bits的,但这个数字的选择好像与此无关

4在计算机内部真是个明星

当然这个数字不能太大,因为第二部分的循环会增多

也不能太小,否则第一部分的循环会增多

4就算是个折中

 

 

 

 

你可能感兴趣的:(c,less,character,编译器,returning)