大家好,欢迎来到IT知识分享网。
序言
总结strdup、strcpy、strncpy和memcpy几个函数的使用和区别,并举例说明。
1. strdup函数
- 函数原型:char *strdup(const char *s);
- 头文件:string.h
- 函数功能:先用malloc()函数分配与参数s字符串相同的大小空间,然后将参数s字符串的内容复制到该内存地址,再将该地址返回。
- 注意:记得free()内存。
- 函数返回值:
- 成功返回:字符串指针,指向复制后的新字符串地址
- 失败返回:返回NULL表示内存不足
- 函数glibc参考实现
char *__strdup(const char *s) { size_t len = strlen(s) + 1; void *new = malloc(len); if (new == NULL); return NULL; return (char *)memcpy(new, s, len); }
函数内部使用了:strlen,malloc,memcpy三个函数
strlen:不计入字符串结束符\0
malloc:一般与free成对使用
memcpy:内存复制。不关心数据类型,不因\0而结束。
2. strcpy函数
- 函数原型:char *strcpy(char *dest, const char *src);
- 头文件:string.h
- 函数功能:将包括NULL在内的src字符串内容复制到dest指向的数组
- dest和src地址不能重叠,dest必须有足够空间存储包括NULL在内的src内容
- 返回值:
- 成功返回:指向dest的起始地址
- strdup和strcpy
- 两个函数都实现了字符串的拷贝,返回char *dest地址
- strdup会根据要复制内容的大小自动分配空间
- strcpy目的指针一定是已经分配好的内存指针
- strdup的缺点:因为是在函数内部malloc空间,有可能导致忘记free空间
- strcpy的缺点:主动分配空间如果不够大,会造成内存溢出buffer overflow
- 补充介绍strncpy函数
- 函数原型: char * strncpy( char *dest, const char *src, size_t n);
- 将字符串src前n个字符拷贝到字符串dest
- 返回值:返回dest地址
- 注意点:
- dest和src地址不能重叠,dest必须有足够空间放置n个字符
- 不像strcpy,strncpy不会在字符串结尾自动加\0,需要主动加上结束符NULL或使n等于strlen(src) + 1,否则可能打出一些杂乱无章的字符
- 函数原型: char * strncpy( char *dest, const char *src, size_t n);
3. memcpy函数
- 函数原型: void * memcpy ( void * dest, const void * src, size_t num );
- 返回类型为void指针,可以自行配置
- 头文件:string.h
- 函数功能:复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上
- strncpy函数功能与memcpy函数功能相似,但有两点区别,见下
- memcpy和strncpy和strcpy和strdup:
- [1] 除了strdup,都需要提前为目的地址分配空间
- [2] 除了memcpy,strcpy、strdup、strncpy都会因为遇到\0而终止
- strcpy复制\0之前的字符,复制遇\0截止
- strdup只申请了能存储\0及之前字符的空间,因为使用了strlen,统计遇\0截止
- strncpy虽也是复制n个字符,但同样,复制遇到\0截至
- [3] 相对于strncpy,memcpy不关心复制的数据类型,可以面向任何数据类型进行复制,可进行强制类型转换
- [4] 都返回复制后的dest地址,除了memcpy,都是char *类型
函数区别举例说明
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<malloc.h> //_msize() int main() { char str[] = "1234abcd\0XYZ"; printf("%d\n", strlen(str)); //strlen统计,遇\0截止 printf("%d\n", sizeof(str)); //sizeof统计整个字符串包括\0长度 /* 各函数使用 */ //strcpy() char str1[10]; strcpy(str1, str); //返回dest地址,char *类型 printf("%c\n", str1[7]); printf("%c\n", str1[9]); //看字符'X'是否复制过去 //strdup() char *str2 = strdup(str); //返回自申请的空间地址,char *类型 printf("%d\n", _msize(str2)); //通过_msize统计申请了多少空间 //strncpy() char *str3 = (char *)malloc(sizeof(char) * 15); strncpy(str3, str, 13); //返回dest地址,char *类型 str3[12] = '\0'; //主动添加结束符,也可以复制size + 1来将\0复制进去 printf("%c\n", str3[11]); //看字符'Z'是否复制过去 printf("%s\n", str3); //memcpy() char *str4 = (char *)malloc(sizeof(char) * 15); memcpy(str4, str, sizeof(str)); //返回dest地址,void *类型 printf("%c\n", str4[11]); //看字符'Z'是否复制过去 free(str2); free(str3); free(str4); return 0; }
- 输出:建议使用memcpy进行赋值,不过需注意空间大小和指针类型
| 8【strlen()统计,遇\0截止】 |
| 13 【sizeof()统计整个数组,包括\0在内的长度】 |
| d 【字符’d’复制过去了】 |
| @ 【字符’X’没有复制过去,说明strcpy()复制遇’\0’截止】 |
| 9 【长度只有”1234abcd\0”长度,说明strdup只申请了遇’\0’之前的空间】 |
| 【输出为空,说明strncpy()复制也是遇’\0’截止】 |
| 1234abcd 【strncpy()复制遇’\0’截止】 |
| Z 【memcpy()复制满n个字符为止,返回void *地址】 |
Acknowledgements:
http://book.51cto.com/art/201311/419443.htm
http://c.biancheng.net/cpp/html/164.html
http://c.biancheng.net/cpp/html/155.html
http://www.cnblogs.com/absolute8511/archive/2009/01/14/1649612.html
2017.08.28
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117859.html