sprintf、strcpy及 memcpy 函数

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个字节

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容