美文网首页C语言
sprintf、strcpy及 memcpy 函数

sprintf、strcpy及 memcpy 函数

作者: PersisThd | 来源:发表于2019-06-05 11:05 被阅读5次

    1、sprintf和snprintf

    int sprintf(char *buffer, const char *format, [argument] ... );
    

    功能:将格式化的数据写入某个字符串缓冲区
    入参:format,输出字符串的格式化列表,比如%d、%s、%c等
    入参:format对应的不定参数列表,与printf类似
    出参:buffer,指向一段存储空间,用于存储格式化之后的字符串
    返回值:返回写入buffer的字符数,出错则返回-1

    //sprintf用法
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
        char buffer[10];
        const int a = 12345;
        const char *b = "102938465839202";
        
        sprintf(buffer, "%d", a);  //将变量a按int类型打印成字符串,输出到buffer中
        sprintf(buffer, "%d+%s", a, b);  //将变量a和字符串b连接成一个字符串输出到buffer中
        
        return 0;
    }
    

    输出分析:
    如果输出到buffer的内容长度不超过10个字节,那么此时sprintf的操作是没有风险的;
    如果超过了10个字节,那么就会导致buffer存储空间溢出,从存储位置上分析,buffer空间是一个栈空间,在它自己10个字节以外的空间是其他栈变量的存储空间,一旦sprintf将10字节外的其他空间也操作了,这就有可能破坏了其他栈变量的内容,这有可能是致命的

    int snprintf(char *buffer, size_t size, const char *format, [argument] ... );
    

    功能: 有长度限制地,把格式化的数据写入某个字符串缓冲区
    入参:format,输出字符串的格式化列表,比如"%s %d %c"等
    入参: [argument],format对应的不定参数列表,与printf的不定入参类似
    入参:size,表示buffer指向存储空间的大小
    出参:buffer,指向一段存储空间,用于存储格式化之后的字符串返回值:返回写入buffer 的字符数,出错则返回-1. 如果 buffer 或 format 是空指针,且不出错而继续,函数将返回-1,并且 errno 会被设置为 EINVAL

    //snprintf用法
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
        char buffer[10];
        const int a = 12345;
        const char *b = "102938465839202";
        
        snprintf(buffer, sizeof(buffer), "%d", a);  //将变量a按int类型打印成字符串,输出到buffer中
        snprintf(buffer, sizeof(buffer), "%d+%s", a, b);  //将变量a和字符串b连接成一个字符串输出到buffer中
        
        return 0;
    }
    

    输出分析:
    如果格式化后的字符串长度 < size,则将字符串全部复制到buffer中,并给其后面添加一个字符串结束符'\0';
    如果格式化后的字符串长度 >= size,则将(size-1)个字符串复制到buffer中,并给其后添加一个字符串结束符'\0',返回值为欲写入的字符串长度

    结论:snprintf是sprintf的安全版本

    1、strcpyf和strncpy

    char *strcpy(char *dest, const char *src);
    

    功能:将参数src字符串拷贝至参数dest所指的地址,会自动给dest字符串补结束符'\0';
    返回值:返回dest的字符串的起始地址;
    说明:如果参数dest所指向的内存空间不够大,可能会造成缓冲溢出的错误情况(同sprintf)。

    //strcpy用法
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char src[] = "abcde\0jjih";
        char dst[] = "amjihgknsnsn";
        strcpy(dst, src);
    
        printf("%s\n", dst);
    
        return 0;
    }
    

    输出分析:
    strcpy在拷贝时遇到结束符'\0'就停止拷贝,拷贝到dst之后,会在拷贝的字符串后面自动补上结束符'\0',因此输出的结果是abcde

    char *strncpy(char *dest, const char * src, size_t n);
    

    函数说明:strncpy()会将字符串src的前n个字符拷贝到字符串dest;
    返回值:返回字符串dest
    注意:strncpy()不会像strcpy那样向dest追加结束符,但是它可以拷贝结束符,结束符之后的字符不能够拷贝,src和dest所指向的内存区域不能重叠,且dest必须由足够大的空间放置n个字符

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char dest1[20];
        char src1[] = "abc";
        int n1 = 3;
        char dest2[20] = "***************";
        char src2[] = "abcxyz";
    
        int n2 = strlen(src2)+1;
        char dest3[100] = "www.baidu.com";
        char src3[6] = "abcxyz";   //没有结束符
        int n3 = 20;
        char dest4[100] = "www.google.com";
        char src4[] = "abc\0defghijk";
        int n4 = strlen(src3);
    
        strncpy(dest1, src1, n1);   //
        strncpy(dest2, src2, n2);
        strncpy(dest3, src3, n3);
        strncpy(dest4, src4, n4);
    
        printf("dest1 = %s\n", dest1);
        printf("dest2 = %s, dest2[15] = %c", dest2, dest2[10]);
        printf("dest3 = %s\n", dest3);
        printf("dest4 = %s\n, dest4[6] = %d, dest4[20] = %d, dest4[90] = %d\n", dest4, dest4[6], dest4[20], dest4[90]);
    
        return 0;
    }
    

    输出分析:
    n1小于strlen(src1)+1,不会追加'\0';
    n2等于strlen(src2)+1,恰好可以把src2末尾的'\0'拷贝到dest2
    n3大于strlen(src3)+1,循环拷贝str3
    src4中出现'\0',其之后的内容不会拷贝

    3、memcpy

    void memcpy(void *dest, const void *src, size_t n);
    

    功能:将src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内
    返回值:返回一个指向dest的指针
    注意:src和dest所指向的内存区域不能重叠;与strcpy相比,memcpy并不是遇到结束符就停止拷贝,而是一定会拷贝完n个字节

    相关文章

      网友评论

        本文标题:sprintf、strcpy及 memcpy 函数

        本文链接:https://www.haomeiwen.com/subject/bizkxctx.html