linux中strcpy strncpy memcpy sprintf snprintf区别总结

来源:互联网 发布:淘宝大c家有买假货吗 编辑:程序博客网 时间:2024/05/22 06:54

strcpy

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

strcpy 函数操作的对象是字符串,完成从源字符串src到目的字符串dest的拷贝功能,会把字符串结尾的'\0'一起拷贝,并且也只拷贝到'\0'就结束。所以需要保证dest空间足够大,不然会导致内存溢出。

安全隐患:内存溢出。

strncpy

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

其它strcpy类似,只是最多只拷贝n个字节。

注意:

1、如果在src的前n个字节里面不包括'\0',那么拷贝到dest中的n字符串就不会以'\0'结束。

2、如果在src的前n个字节里面包括'\0',即src字符串的长度小于n,那么只拷贝到'\0'结束,并且剩下的空间会被填充'\0'。

#include <stdio.h>#include <string.h>int main(){    char psz_dest1[6] = "aaaaa";    char psz_dest2[11] = "aaaaaaaaaa";    char *psz_src1 = "1234";    char *psz_src2 = "1234567";    char *psz_src3 = "12345678901234567890";    printf( "psz_dest1: %s\n", psz_dest1 );    strcpy( psz_dest1, psz_src1 );    printf( "psz_dest1: %s\n", psz_dest1 );        //strcpy( psz_dest1, psz_src2 );    //printf( "psz_dest1: %s\n", psz_dest1 );       // print 1234567 and then may be lots of error information    printf( "psz_dest2: %s\n", psz_dest2 );    strncpy( psz_dest2, psz_src2, sizeof( psz_dest2 ) );    printf( "psz_dest2: %s\n", psz_dest2 );    //strncpy( psz_dest2, psz_src3, 15 );    //printf( "psz_dest2: %s\n", psz_dest2 );   // print 123456789012345 and then may be lots of error information    return 0;}

输出:

psz_dest1: aaaaa
psz_dest1: 1234
psz_dest2: aaaaaaaaaa
psz_dest2: 1234567

memcpy

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

memcpy 函数顾名思义就是内存拷贝,实现将一个内存块的内容复制到另一 内存块。内存块由其首地址以及长度确定。程序中出现的实体对象,不论是什么类型,其最终表现就是在内存中占据一席之地(一个内存区间或块)。因此,memcpy 的操作对象不局限于某一类数据类型,或者说可适用于任意数据类型,只要能给出对象的起始地址和内存长度信息、并且对象具有可操作性即可。鉴于 memcpy 函数等长拷贝的特点以及数据类型代表的物理意义,memcpy 函数通常限于同种类型数据或对象之间的拷贝,其中当然也包括字符串拷贝以及基本数据类型的拷贝。

memcpy总会拷贝n个字节,不论有没有遇到'\0'。

sprintf

int sprintf(char *str, const char *format, ...);

sprintf 函数操作的对象不限于字符串:虽然目的对象是字符串,但是源对象可以是字符串、也可以是任意基本类型的数据。这个函数主要用来实现字符串或基本数据类型向字符串的转换功能。如果源对象是字符串,并且指定 %s 格式符,也可实现字符串拷贝功能。

sprintf对于源是字符串的,也跟strcpy一样,拷贝到才'\0'截止。所以也存在内存泄露问题。

snprintf

int snprintf(char *str, size_t size, const char *format, ...);

也是实现字符串或基本数据类型向字符串的转换功能。

1、跟sprintf不同的是,只会拷贝(n - 1)个字节,然后自动在后面加一个'\0',加起来总共n,实际strlen(str)为 n-1。见下面例子的输出2和3。

2、跟strncpy比较,strncpy会拷贝n个字节,实际strlen(dest)为到'\0'的长度。见下面例子的输出4和5。

3、sprintf和snprintf中,绝对不能使目标地址和源地址相同,不然会拷贝失败。见下面的例子的输出6和7。

4、二者都有性能问题。如果src远大于dest,用strncpy;如果dest远大于src,用snprintf。

由于snprintf会自动加上'\0',所以,snprintf比strncpy使用简单。

下面的例子的输出8和9说明strcpy和sprintf都是拷贝到'\0'才截止。

#include <stdio.h>#include <string.h>int main(){    char astr[6];    char ss[] = "1234567890";    memset( astr, 'a', sizeof(astr) );    printf("1 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    snprintf(astr, sizeof(astr) - 1, "%s", ss);    printf("2 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );        astr[sizeof(astr) - 2] = '\0';     printf("3 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    memset( astr, 'a', sizeof(astr) );    strncpy(astr, ss, sizeof(astr) - 1);    printf("4 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );        astr[sizeof(astr) - 2] = '\0';     printf("5 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    memset( astr, 'a', sizeof(astr) );    sprintf( astr, "b%s", astr );    printf("6 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    memset( astr, 'a', sizeof(astr) );    snprintf( astr, sizeof(astr), "b%s", astr );    printf("7 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    memset( astr, 'a', sizeof(astr) );    strcpy(astr, ss);    printf("8 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );    memset( astr, 'a', sizeof(astr) );    sprintf(astr, "%s", ss);    printf("9 astr: %s, strlen(astr): %d\n", astr, strlen(astr) );        return 0;}



输出:

1 astr: aaaaaa, strlen(astr): 6
2 astr: 1234, strlen(astr): 4
3 astr: 1234, strlen(astr): 4
4 astr: 12345a, strlen(astr): 6
5 astr: 1234, strlen(astr): 4
6 astr: bbbbbbb, strlen(astr): 7
7 astr: bbbbb, strlen(astr): 5
8 astr: 1234567890, strlen(astr): 10
9 astr: 1234567890, strlen(astr): 10

后面是很多错误信息,因为越界了。

第一个结果不确定,有可能是aaaaaa加上很多乱码,长度看'\0'在内存中的位置。

http://blog.sina.com.cn/s/blog_7c50857d0101492l.html


0 0
原创粉丝点击