C标准库源码解剖(5):字符串处理函数string.h和wchar.h(续)
分类:C 2009-10-08 12:46 500人阅读评论(0) 收藏举报
3、字符串复制strcpy,strncpy,wcscpy,wcsncpy:将字符串src(或其前n个字符)复制到dest中,覆盖dest的内容。实现中先检查指针是否越界,计算指针dest到src的偏移,然后开始做复制操作,复制到dest的开始位置处,以覆盖dest的内容。对strncpy,也采用了每4个字符作为一组来进行复制的方法,以加快复制速度。
view plaincopy to clipboardprint?
1. /* strcpy.c:strcpy函数的实现 */
2. #include <stddef.h>  /* 用到了ptrdiff_t */
3. #include <string.h>
4. #include <memcopy.h>
5. #include <bp-checks.h>  /* 定义了CHECK_BOUNDS_LOW和
CHECK_BOUNDS_HIGH */
6. #undef strcpy
7. /* 将SRC复制到DEST中,覆盖DEST原先的内容 */
8. c har *
9. s trcpy (dest, src)
10.      char *dest;
11.      const char *src;
12. {
13.  reg_char c;
14.  /* 检查指针src的值是否 >= low,返回原来的指针值 */
15.  char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src)
sizeof 指针;
16.  /* 计算出目的地dest到s的偏移 */
17.  const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
18.  size_t n;
19.  do
20.    {
21.      c = *s++;  /* 把src中每个字符复制到目的地,覆盖了dest中的内容 */
22.      s[off] = c;
23.    }
24.  while (c != '/0');
25.  n = s - src;
26.  (void) CHECK_BOUNDS_HIGH (src + n); /* 检查指针src+n的值是否 < high,
返回原来的指针值 */
27.  (void) CHECK_BOUNDS_HIGH (dest + n);
28.  return dest;
29. }
30. libc_hidden_builtin_def (strcpy)
1. /* strncpy.c:strncpy函数的实现  */
2. #include <string.h>
3. #include <memcopy.h>
4. #undef strncpy
5. /* 将s2的前n个字符复制到s1中,覆盖s1原先的内容,若s2不中n个字符,
6. 则填充null字符,直到写入n个字符 */
7. c har *
8. s trncpy (s1, s2, n)
9. char *s1;
10.      const char *s2;
11.      size_t n;
12. {
13.  reg_char c;
14.  char *s = s1;
15.  --s1; /* 指向首字符的前一个字符 */
16.  if (n >= 4)    /* 做复制操作,每4个字符作为一组来进行复制 */
17.    {
18.      size_t n4 = n >> 2; /* 让n除以4,计算出循环次数 */
19.      for (;;)  /* 每次循环都复制4个字符,总共复制了4*n4个字符 */
20.    {
21.      c = *s2++;
22.      *++s1 = c;
23.      if (c == '/0') /* s2不足n个字符时,复制完毕,退出循环 */
24.        break;
25.      c = *s2++;
26.      *++s1 = c;
27.      if (c == '/0')
28.        break;
29.      c = *s2++;
30.      *++s1 = c;
31.      if (c == '/0')
32.        break;
33.      c = *s2++;
34.      *++s1 = c;
35.      if (c == '/0')
36.        break;
37.      if (--n4 == 0)
38.        goto last_chars; /* 循环终止,要对剩下的几个字符(不超过3个)进行复
制 */
39.    }
40.      n = n - (s1 - s) - 1;
41.      if (n == 0)  /* 若s1恰好到达s的终止符的前一个字符处 */
42.    return s;  /* 说明s与s2长度相等,均为n,复制操作恰好用s2覆盖了s,终
止符没有覆盖,直接返回s */
43.      goto zero_fill; /* 否则s1没有到达s的末尾,说明s2不足n个字符,需要在
s1末尾填充null字符,直到写入n个字符 */
44.    }
45.  last_chars:
46.  n &= 3; /* 求出n除以4的余数 */
47.  if (n == 0)  /* 余数为0说明没有剩余的未复制的字符,直接返回s */
48.    return s;
49.  do  /* 对剩下的几个字符(最多3个)进行复制 */
50.    {
51.      c = *s2++;
52.      *++s1 = c;
53.      if (--n == 0)
54.    return s;
55.    }
56.  while (c != '/0');
57.  zero_fill:
58.  do
59.    *++s1 = '/0';  /* 在s1末尾填充null字符,直到写入n个字符 */
60.  while (--n > 0);
61.  return s;
62. }
63. libc_hidden_builtin_def (strncpy)
1. /* strlen.c:strlen函数的实现 */
2. #include <string.h>
3. #include <stdlib.h>  /* 用到abort()函数 */
4. #undef strlen
5. /* 返回以null终止的字符串str的长度。通过一次测试4个字节来迅速的扫描到null
终止符 */
6. s ize_t
7. s trlen (str)
8.    const char *str;
9. {
10.  const char *char_ptr;
11.  const unsigned long int *longword_ptr;
12.  unsigned long int longword, magic_bits, himagic, lomagic;
13.  /* 通过一次读取一个字符来处理开头的几个字符,直到char_ptr中的值对齐到
一个long型字的边界,
14.      即直到char_ptr中的值是long的字节数(通常为4)的倍数 */
15.  for (char_ptr = str; ((unsigned long int) char_ptr
16.            & (sizeof (longword) - 1)) != 0;
17.        ++char_ptr)
18.    if (*char_ptr == '/0') /* 若到达null终止符,则直接返回长度 */
19.      return char_ptr - str;
20.  /* 所有这些说明性的注释使用4字节的long型字,但本算法同样也可以应用于
8字节的long型字 */
21.
22.  longword_ptr = (unsigned long int *) char_ptr;
23.  /* magic_bits的第8,16,24,31位为0,称这些位为“洞”。注意每个字节的左边
有一个洞,
24.      在最后的位置上也有一个洞。
25.      bits:  01111110 11111110 11111110 11111111
26.      比特1确保进位能传播到后面的比特0上,比特0则提供洞,以便让进位陷
进去  */
27.  magic_bits = 0x7efefeffL;
28.  himagic = 0x80808080L;  /* 高位魔数,即第7,15,23,31位上为1 */
29.  lomagic = 0x01010101L;  /* 低位魔数,即第0,8,16,24位上为1 */
30.  if (sizeof (longword) > 4) /*  64位的平台上 */
31.    {
32.      /* 魔数的64位版本 */
33.      /* 移位操作分两步,以避免当long为32位时出现警告 */

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。