(转)glibc中字符串函数源码分析

3、字符串复制strcpy,strncpy,wcscpy,wcsncpy:将字符串src(或其前n个字符)复制到dest中,覆盖dest的内容。实现中先检查指针是否越界,计算指针dest到src的偏移,然后开始做复制操作,复制到dest的开始位置处,以覆盖dest的内容。对strncpy,也采用了每4个字符作为一组来进行复制的方法,以加快复制速度。

view plaincopy to clipboardprint?
/* strcpy.c:strcpy函数的实现 */ 
#include <stddef.h>   /* 用到了ptrdiff_t */   
#include <string.h>   
#include <memcopy.h>   
#include <bp-checks.h> /* 定义了CHECK_BOUNDS_LOW和CHECK_BOUNDS_HIGH */   
#undef strcpy   
/* 将SRC复制到DEST中,覆盖DEST原先的内容 */ 
char *   
strcpy (dest, src)   
     char *dest;   
     const char *src;   
{   
reg_char c;   
/* 检查指针src的值是否 >= low,返回原来的指针值 */ 
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);   
/* 计算出目的地dest到s的偏移 */ 
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;   
size_t n;   
do 
    {   
      c = *s++;   /* 把src中每个字符复制到目的地,覆盖了dest中的内容 */ 
      s[off] = c;   
    }   
while (c != '\0');   
n = s - src;   
(void) CHECK_BOUNDS_HIGH (src + n); /* 检查指针src+n的值是否 < high,返回原来的指针值 */ 
(void) CHECK_BOUNDS_HIGH (dest + n);   
return dest;   
}   
libc_hidden_builtin_def (strcpy) 
/* strcpy.c:strcpy函数的实现 */
#include <stddef.h>   /* 用到了ptrdiff_t */
#include <string.h>
#include <memcopy.h>
#include <bp-checks.h> /* 定义了CHECK_BOUNDS_LOW和CHECK_BOUNDS_HIGH */
#undef strcpy
/* 将SRC复制到DEST中,覆盖DEST原先的内容 */
char *
strcpy (dest, src)
     char *dest;
     const char *src;
{
reg_char c;
/* 检查指针src的值是否 >= low,返回原来的指针值 */
char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);
/* 计算出目的地dest到s的偏移 */
const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;
size_t n;
do
    {
      c = *s++;   /* 把src中每个字符复制到目的地,覆盖了dest中的内容 */
      s[off] = c;
    }
while (c != '\0');
n = s - src;
(void) CHECK_BOUNDS_HIGH (src + n); /* 检查指针src+n的值是否 < high,返回原来的指针值 */
(void) CHECK_BOUNDS_HIGH (dest + n);
return dest;
}
libc_hidden_builtin_def (strcpy)

view plaincopy to clipboardprint?
/* strncpy.c:strncpy函数的实现 */ 
#include <string.h>   
#include <memcopy.h>   
#undef strncpy   
/* 将s2的前n个字符复制到s1中,覆盖s1原先的内容,若s2不中n个字符, 
    则填充null字符,直到写入n个字符 */ 
char *   
strncpy (s1, s2, n)   
     char *s1;   
     const char *s2;   
     size_t n;   
{   
reg_char c;   
char *s = s1;   
--s1; /* 指向首字符的前一个字符 */ 
if (n >= 4)     /* 做复制操作,每4个字符作为一组来进行复制 */ 
    {   
      size_t n4 = n >> 2; /* 让n除以4,计算出循环次数 */ 
      for (;;)   /* 每次循环都复制4个字符,总共复制了4*n4个字符 */ 
    {   
      c = *s2++;   
      *++s1 = c;   
      if (c == '\0') /* s2不足n个字符时,复制完毕,退出循环 */ 
        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; /* 循环终止,要对剩下的几个字符(不超过3个)进行复制 */ 
    }   
      n = n - (s1 - s) - 1;   
      if (n == 0) /* 若s1恰好到达s的终止符的前一个字符处 */ 
    return s; /* 说明s与s2长度相等,均为n,复制操作恰好用s2覆盖了s,终止符没有覆盖,直接返回s */ 
      goto zero_fill; /* 否则s1没有到达s的末尾,说明s2不足n个字符,需要在s1末尾填充null字符,直到写入n个字符 */ 
    }   
last_chars:   
n &= 3; /* 求出n除以4的余数 */ 
if (n == 0) /* 余数为0说明没有剩余的未复制的字符,直接返回s */ 
    return s;   
do   /* 对剩下的几个字符(最多3个)进行复制 */ 
    {   
      c = *s2++;   
      *++s1 = c;   
      if (--n == 0)   
    return s;   
    }   
while (c != '\0');   
zero_fill:   
do 
    *++s1 = '\0'; /* 在s1末尾填充null字符,直到写入n个字符 */ 
while (--n > 0);   
return s;   
}   
libc_hidden_builtin_def (strncpy) 
/* strncpy.c:strncpy函数的实现 */
#include <string.h>
#include <memcopy.h>
#undef strncpy
/* 将s2的前n个字符复制到s1中,覆盖s1原先的内容,若s2不中n个字符,
    则填充null字符,直到写入n个字符 */
char *
strncpy (s1, s2, n)
     char *s1;
     const char *s2;
     size_t n;
{
reg_char c;
char *s = s1;
--s1; /* 指向首字符的前一个字符 */
if (n >= 4)     /* 做复制操作,每4个字符作为一组来进行复制 */
    {
      size_t n4 = n >> 2; /* 让n除以4,计算出循环次数 */
      for (;;)   /* 每次循环都复制4个字符,总共复制了4*n4个字符 */
{
   c = *s2++;
   *++s1 = c;
   if (c == '\0') /* s2不足n个字符时,复制完毕,退出循环 */
     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; /* 循环终止,要对剩下的几个字符(不超过3个)进行复制 */
}
      n = n - (s1 - s) - 1;
      if (n == 0) /* 若s1恰好到达s的终止符的前一个字符处 */
return s; /* 说明s与s2长度相等,均为n,复制操作恰好用s2覆盖了s,终止符没有覆盖,直接返回s */
      goto zero_fill; /* 否则s1没有到达s的末尾,说明s2不足n个字符,需要在s1末尾填充null字符,直到写入n个字符 */
    }
last_chars:
n &= 3; /* 求出n除以4的余数 */
if (n == 0) /* 余数为0说明没有剩余的未复制的字符,直接返回s */
    return s;
do   /* 对剩下的几个字符(最多3个)进行复制 */
    {
      c = *s2++;
      *++s1 = c;
      if (--n == 0)
return s;
    }
while (c != '\0');
zero_fill:
do
    *++s1 = '\0'; /* 在s1末尾填充null字符,直到写入n个字符 */
while (--n > 0);
return s;
}
libc_hidden_builtin_def (strncpy)

posted @ 2010-10-23 12:13  elite_lcf  阅读(1800)  评论(0编辑  收藏  举报
知识共享许可协议
本博客采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。