C语言基础-strdup/strcpy/strncpy/memcpy函数的使用

来源:互联网 发布:ubuntu vim找不到命令 编辑:程序博客网 时间:2024/05/18 05:02

序言

总结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,否则可能打出一些杂乱无章的字符


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

阅读全文
0 0
原创粉丝点击