char strcpy(char dest, const char *src);
头文件:#include <string.h> 和 #include <stdio.h>
功能:把从src地址开始且含有’\0’结束符的字符串复制到以dest开始的地址空间
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
标签:危险
char *strncpy(char *destinin, char *source, int maxlen);
strncpy : 拷贝源地址固定个数的字符给目的地址
标签:较危险
这里为了更好理解,将字符串的结束符’\0’也当做一个普通字符。
示例:
#include <stdio.h>
#include <string.h>
char src[5];
char dst[5];
void dump(char *c, int n) {
int i = 0;
for(;i<n;i++) {
printf("c[%d]=%c ", i, c[i]);
}
printf("\n");
}
void init(char *c, int n, char d) {
int i = 0;
for(;i<n;i++) {
c[i] = d;
}
}
int main(){
int len = sizeof(src);
printf("len = %d\n", len);
init(src, len, 's');
init(dst, len, 't');
dump(src, len);
dump(dst, len);
printf("\n");
strncpy(dst, src, 3);
dump(dst,5);
init(dst, len , 't');
strncpy(dst, src, 4);
dump(dst,5);
init(dst, len , 't');
strncpy(dst, src, 5);
dump(dst,5);
init(dst, len , 't');
return 0;
}
#./main
len = 5
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=s
c[0]=t c[1]=t c[2]=t c[3]=t c[4]=t
c[0]=s c[1]=s c[2]=s c[3]=t c[4]=t
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=t
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=s
两种做法:
(1) dst先memset为’\0’,拷贝src的strlen(src)个字符给dst,这样dst就是一个完整字符串
(2)直接拷贝src的strlen(src)+1个字符给dst,这样dst也是一个完整字符串。
问题1:
strncpy支不支持重叠区域的拷贝?
支持
#include <stdio.h>
#include <string.h>
char src[5];
void dump(char *c, int n) {
int i = 0;
for(;i<n;i++) {
printf("c[%d]=%c ", i, c[i]);
}
printf("\n");
}
int main(){
int len = sizeof(src);
printf("len = %d\n", len);
src[0] = src[1] = 's';
src[2] = src[3] = 't';
src[4] = 'k';
strncpy(src+2, src, 2);
dump(src,5);
return 0;
}
#./main1
len = 5
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=k
问题2:
strncpy越界会报错不?
不会报错
#include <stdio.h>
#include <string.h>
char src[5];
char dst[4];
void dump(char *c, int n) {
int i = 0;
for(;i<n;i++) {
printf("c[%d]=%c ", i, c[i]);
}
printf("\n");
}
void init(char *c, int n, char d) {
int i = 0;
for(;i<n;i++) {
c[i] = d;
}
}
int main(){
int len = sizeof(src);
printf("len = %d\n", len);
init(src, len, 's');
init(dst, len-1, 't');
dump(src, len);
dump(dst, len-1);
strncpy(dst, src, len);
dump(dst,len);
return 0;
}
#./main2
len = 5
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=s
c[0]=t c[1]=t c[2]=t c[3]=t
c[0]=s c[1]=s c[2]=s c[3]=s c[4]=s
问题3:
如果src的长度比拷贝的n值小很多,那该怎么拷贝呢?
默认填充’\0’
#include <stdio.h>
#include <string.h>
char src[2];
char dst[4];
void dump(char *c, int n) {
int i = 0;
for(;i<n;i++) {
printf("c[%d]=%c ", i, c[i]);
}
printf("\n");
}
void init(char *c, int n, char d) {
int i = 0;
for(;i<n;i++) {
c[i] = d;
}
}
int main(){
int len = sizeof(dst);
printf("len = %d\n", len);
src[0] = 's';
src[1] = '\0';
init(dst, len, 't');
dump(src, sizeof(src));
dump(dst, len);
strncpy(dst, src, len);
dump(dst,len);
return 0;
}
#./main3
len = 4
c[0]=s c[1]=
c[0]=t c[1]=t c[2]=t c[3]=t
c[0]=s c[1]= c[2]= c[3]=
strlcpy
size_t strlcpy(char *dst, const char *src, size_t dsize)
将src按字符拷贝到dst中,最多拷贝dszie-1个字符,拷贝结束后在dst末尾添加’\0’
返回值:src的长度
一般将dsize置为dst的大小。
相较于strncpy,strlcpy有两个优点:
(1)当strlen(src)大于等于dsize时自动在dst末尾添加结束符;
(2)返回值大于等于dsize时确定发生字符串截断。
以上两点帮助程序员进行判断,方便后续处理。
#include <string.h>
#include <stdio.h>
int main()
{
char buf[5];
char src[10] = "12345678";
strlcpy(buf, src, sizeof(buf));
printf("%s\n",buf);
return 0;
}
上述示例中buf字符串最终结果是“1234\0”。
也就是拷贝完后不管有没有截断,都要进行\0的拷贝。
缺点:
strlcpy和strlcat是BSD的C库函数,glibc维护者一直拒绝将其加入,所以需要安装额外的包。
apt-get install libbsd-dev
strlcpy安全吗?
留后续验证。睡觉