推扬网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
推扬网 门户 你问我答 查看内容

刘浩然:strncpy()函数的功能

2020-8-11 15:44| 发布者: admin| 查看: 99| 评论: 0

摘要: 可拉拉的回答: strcpy ,strncpy ,strlcpy地用法 好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。 但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。 1. strcpy 我们知道,strcpy 是依据 /0 作 ...

可拉拉的回答:

strcpy ,strncpy ,strlcpy地用法 好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。 但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。 1. 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 不够安全。 2. 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); 3. strlcpy // Copy src to string dst of size siz. At most siz-1 characters // will be copied. Always NUL terminates (unless siz == 0). // Returns strlen(src); if retval >= siz, truncation occurred. size_t strlcpy(char *dst, const char *src, size_t siz); 而使用 strlcpy,就不需要我们去手动负责 /0 了,仅需要把 sizeof(dst) 告之 strlcpy 即可: strlcpy(path, src, sizeof(path)); len = strlen(path); if ( len >= sizeof(path) ) printf("src is truncated."); 并且 strlcpy 传回的是 strlen(str),因此我们也很方便的可以判断数据是否被截断。 [* 一点点历史 *] strlcpy 并不属于 ANSI C,至今也还不是标准。 strlcpy 来源于 OpenBSD 2.4,之后很多 unix-like 系统的 libc 中都加入了 strlcpy 函数,我个人在 FreeBSD、Linux 里面都找到了 strlcpy。(Linux使用的是 glibc, glibc里面有 strlcpy,则所有的 Linux 版本也都应该有 strlcpy) 但 Windows 下是没有 strlcpy 的,对应的是strcpy_s函数 /////////////////////////////////////////////////////////////////////////// strncpy 原型:extern char *strncpy(char *dest, char *src, int n); 用法:#include <string.h> 功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中。 说明: 如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束。 如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。 src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 返回指向dest的指针。 举例: // strncpy.c #include <syslib.h> #include <string.h> main() { char *s="Golden Global View"; char *d="Hello, GGV Programmers"; char *p=strdup(s); clrscr(); textmode(0x00); // enable 6 lines mode strncpy(d,s,strlen(s)); printf("%s/n",d); strncpy(p,s,strlen(d)); printf("%s",p); getchar(); return 0; } ------------------------------ memcpy 原型:extern void *memcpy(void *dest, void *src, unsigned int count); 用法:#include <string.h> 功能:由src所指内存区域复制count个字节到dest所指内存区域。 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。 举例: // memcpy.c #include <syslib.h> #include <string.h> main() { char *s="Golden Global View"; char d[20]; clrscr(); memcpy(d,s,strlen(s)); d[strlen(s)]=0; printf("%s",d); getchar(); return 0; }

陈梦瑶的回答:

strcpy ,strncpy ,strlcpy地用法 好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。 但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。 1. 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 不够安全。 2. 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); 3. strlcpy // Copy src to string dst of size siz. At most siz-1 characters // will be copied. Always NUL terminates (unless siz == 0). // Returns strlen(src); if retval >= siz, truncation occurred. size_t strlcpy(char *dst, const char *src, size_t siz); 而使用 strlcpy,就不需要我们去手动负责 /0 了,仅需要把 sizeof(dst) 告之 strlcpy 即可: strlcpy(path, src, sizeof(path)); len = strlen(path); if ( len >= sizeof(path) ) printf("src is truncated."); 并且 strlcpy 传回的是 strlen(str),因此我们也很方便的可以判断数据是否被截断。 [* 一点点历史 *] strlcpy 并不属于 ANSI C,至今也还不是标准。 strlcpy 来源于 OpenBSD 2.4,之后很多 unix-like 系统的 libc 中都加入了 strlcpy 函数,我个人在 FreeBSD、Linux 里面都找到了 strlcpy。(Linux使用的是 glibc, glibc里面有 strlcpy,则所有的 Linux 版本也都应该有 strlcpy) 但 Windows 下是没有 strlcpy 的,对应的是strcpy_s函数 /////////////////////////////////////////////////////////////////////////// strncpy 原型:extern char *strncpy(char *dest, char *src, int n); 用法:#include <string.h> 功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中。 说明: 如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束。 如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。 src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 返回指向dest的指针。 举例: // strncpy.c #include <syslib.h> #include <string.h> main() { char *s="Golden Global View"; char *d="Hello, GGV Programmers"; char *p=strdup(s); clrscr(); textmode(0x00); // enable 6 lines mode strncpy(d,s,strlen(s)); printf("%s/n",d); strncpy(p,s,strlen(d)); printf("%s",p); getchar(); return 0; } ------------------------------ memcpy 原型:extern void *memcpy(void *dest, void *src, unsigned int count); 用法:#include <string.h> 功能:由src所指内存区域复制count个字节到dest所指内存区域。 说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。 举例: // memcpy.c #include <syslib.h> #include <string.h> main() { char *s="Golden Global View"; char d[20]; clrscr(); memcpy(d,s,strlen(s)); d[strlen(s)]=0; printf("%s",d); getchar(); return 0; }

zsh的回答:

char * strncpy(char *s1,char *s2,size_t n); 将字符串s2中最多n个字符复制到字符数组s1中,返回指向s1的指针。 注意:如果源串长度大于n,则strncpy不复制最后的'\0'结束符,所以是不安全的,复制完后需要手动添加字符串的结束符才行。 strcpy和strncpy的区别- - 第一种情况: char* p="how are you ?"; char name[20]="abcdefghijklmnopqrs"; strcpy(name,p); //name改变为"how are you ? "====>正确! strncpy(name,p,sizeof(name)); //name改变为"how are you ? " ====>正确! 第二种情况: char* p="how are you ?"; char name[10]; strcpy(name,p); //目标串长度小于源串,错误! name[sizeof(name)-1]='\0'; //和上一步组合,弥补结果,但是这种做法并不可取,因为上一步出错处理方式并不确定 strncpy(name,p,sizeof(name)); //源串长度大于指定拷贝的长度sizeof(name),注意在这种情况下不会自动在目标串后面加'\0' name[sizeof(name)-1]='\0'; //和上一步组合,弥补结果 ================================================ 总结:strcpy 源字串全部拷贝到目标字串中,包括'\0',但是程序员必须保证目标串长度足够,且不与源串重叠。 strncpy 如果目标长>=指定长>源长,则将源串全部拷贝到目标串,连同'\0' 如果指定长<源长,则将截取源串中按指定长度拷贝到目标字符串,不包括'\0' 如果指定长>目标长,错误!


鲜花

握手

雷人

路过

鸡蛋

最新评论

热门推荐
最新资讯

广告服务|投稿要求|禁言标准|版权说明|免责声明|手机版|小黑屋|推扬网 ( 粤ICP备18134897号 )|网站地图 | 邮箱:vayae@hotmail.com

GMT+8, 2025-5-1 09:49 , Processed in 0.060799 second(s), 29 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

返回顶部