C标准库函数strcpy,strncpy,strlcpy
#include<stdio.h>
snprintf(char* dest_str,size_t size,const char* format,…)
// 函数功能:先将可变参数 “…” 按照format的格式格式化为字符串,然后再将其拷贝至dest_str中。
// 注意:格式化后的字符串长度小于size,则全部拷贝,并在结尾添加'\0'。若大于等于size,则只拷贝size-1,并在结尾添加'\0'
int snprintf(char* dest_str,size_t size,const char* format,...);
char *s1 = "Linux C程序设计";
int size = strlen(s1);
int year = 2017;
int month = 9;
int day = 8;
snprintf(dest_str,sizeof(dest_str),"字符串:%s\n长度是:%d\n今天是:%d年%d月%d日\n",s1,size,year,month,day);
printf("%s",dest_str);
>>> 字符串:Linux C程序设计
长度是:15
今天是:2017年9月8日
// 实例
strcpy ,strncpy ,strlcpy的用法
strcpy ,strncpy ,strlcpy地用法
好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。
但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。
-
strcpy
我们知道,strcpy 是依据 ‘/0’ 作为结束判断的,如果 to 的空间不够,则会引起 buffer overflow。strcpy 常规的实现代码如下(来自 OpenBSD 3.9):
char *strcpy(char *to, const char *from) { char *save = to; for (; (*to = *from) != '/0'; ++from, ++to); return(save); }
但通常,我们的 from 都来源于用户的输入,很可能是非常大的一个字符串,因此 strcpy 不够安全。
-
strncpy
在 ANSI C 中,strcpy 的安全版本是 strncpy。
char *strncpy(char *s1, const char *s2, size_t n)
但 strncpy 其行为是很诡异的(不符合我们的通常习惯)。标准规定 n 并不是 sizeof(s1),而是要复制的 char 的个数。一个最常见的问题,就是 strncpy 并不帮你保证 '/0’结束。char buf[8]; strncpy( buf, "abcdefgh", 8 );
看这个程序,buf 将会被 “abcdefgh” 填满,但却没有 ‘/0’ 结束符了。
另外,如果 s2 的内容比较少,而 n 又比较大的话,strncpy 将会把之间的空间都用 ‘/0’ 填充。这又出现了一个效率上的问题,如下:char buf[80]; strncpy( buf, "abcdefgh", 79 );
上面的 strncpy 会填写 79 个 char,而不仅仅是 “abcdefgh” 本身。
strncpy 的标准用法为:(手工写上 /0)strncpy(path, src, sizeof(path) - 1); path[sizeof(path) - 1] = '/0'; len = strlen(path);
-
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz);
而使用 strlcpy,就不需要我们去手动负责 ‘/0’ 了,仅需要把 sizeof(dst) 告之 strlcpy 即可:
size_t Test_strlcpy(char *dest, const char *src, size_t size
{
size_t ret = strlen(src);
if (size)
{
//这句判断大赞,起码有效防止源字符串的越界问题
size_t len = (ret >= size) ? size - 1 : ret;
memcpy(dest, src, len);
dest[len] = '\0';
}
return ret;
}