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小时内删除。
发表评论