(转)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)