strcpy/strncpy,sprintf/snprintf,strncpy/snprintf的区别


下面的测试基于VS2019,测试过程中会报错并提示使用诸如strcpy_s建议,只需要屏蔽报错强制编译执行即可——在代码开头加上:

#pragma warning(disable:4996)//4996为提示的错误码

1.strcpy/strncpy

char *strcpy(char *dest, const char *src);
char * strncpy(char *dest, const char *src, size_t n);
  • dest 为目标字符串指针,src 为源字符串指针。
  • 成功执行后返回目标数组指针 dest。
  • strcpy() 把src所指的字符串复制到dest 所指的数组中,返回指向 dest 字符串的起始地址。
  • strncpy()会将字符串src前n个字符拷贝到字符串dest。
  • srrncpy()不会自动添加’\0’
  1. 测试1:strcpy 正常使用,空间足够无越界
    char dest[20];
    char src[12] = "Hello-World";
    strcpy(dest, src);
    printf("dest:%s", dest);
    //输出——dest:Hello-World
  1. 测试2:strcpy dest空间小于src空间
    char dest[10];//小于src空间
    char src[12] = "Hello-World";
    strcpy(dest, src);
    printf("dest:%s\n", dest);
    //输出——dest:Hello-World
    //引发异常:Run-Time Check Failure #2 - Stack around the variable 'dest' was corrupted.
    //即:运行时检查失败 #2 - 变量“dest”周围的堆栈已损坏。
  1. 测试3:strncpy 参数n不超过dest的大小
    char dest[10];//小于src空间
    char src[12] = "Hello-World";
    strncpy(dest, src,9);//参数n=9并没有超出空间限制
    printf("dest:%s", dest);
    //输出——dest:Hello-Wor烫烫烫虥鍨8?s0

目标字符串后面有乱码
原因: print以’\0’标识结尾。而strncpy并不会在拷贝后自动添加’\0’
4. 测试4:手动在dest末尾添加结束符‘\0’

    char dest[10];
    char src[12] = "Hello-World";
    strncpy(dest, src,9);
    dest[9] = '\0';
    printf("dest:%s", dest);
    //输出——dest:Hello-Wor

正常执行

2.sprintf/snprintf

printf 将输出在命令行显示
sprintf/snprintf 将输出赋值给字符串,其余的基本使用方式和printf一致

int sprintf(char *dest, const char *src, ...);
int snprintf(char *dest, size_t n, const char *src, ...);
  • dest 为目标字符串指针,src 为源字符串指针。
  • 返回值为被拷贝的字符串的长度,即src的长度
  • 参数n算上了’\n’,因此实际只拷贝了n-1个字符
  1. 测试1:sprintf正常使用,空间足够无越界
    char dest[20];
    char src[12] = "Hello-World";
    int ret=sprintf(dest, src);
    printf("dest:%s\n ret=%d\n", dest,ret);
    //输出——dest:Hello-World
	//     ret=11
  1. 测试2:sprintf dest空间小于src空间
    char dest[10];//小于src的空间
    char src[12] = "Hello-World";
    int ret=sprintf(dest, src);
    printf("dest:%s\nret=%d\n", dest,ret);
    //输出——dest:Hello-World
	//     ret=11
	//同时引发异常:Run-Time Check Failure #2 - Stack around the variable 'dest' was corrupted.
    //即:运行时检查失败 #2 - 变量“dest”周围的堆栈已损坏。
  1. 测试3:snprintf 参数n不超过dest的大小
    char dest[10];
    char src[12] = "Hello-World";
    int ret=snprintf(dest,7,src);
    printf("dest:%s\nret=%d\n", dest,ret);
    printf("dest length=%d\n", strlen(dest));
    //输出——
    //dest:Hello-
    //ret=11
    //dest length=6

可以看出dest的长度 比参数n少1

3.strncpy/snprintf

从上面strcpy/strncpy,sprintf/snprintf两个测试3可以看出strncpy/snprintf的区别如下:

  1. 返回值:strncpy是返回目标dest指针,snprintf返回的是被拷贝的字符数,即src的字符数(注意这里不是成功拷贝的字符数)
  2. 参数n:strncpy是实际拷贝的字符数,snprintf实际拷贝了n-1个字符
  3. snprintf会自动在dest末尾加上’\0’字符,这样在输出的时候不会导致越界;而strncpy要想正常输出,需要手动在末尾添加’\0’字符
  4. n的传递:使用sizeof(dest)更安全方便。
引用中提到,snprintfstrncpy都是用于将原字符串拷贝到目的字符串中的函数。然而,它们在细节部分存在一些差别。首先,snprintf是按照指定的格式将原字符串拷贝到目的字符串中,而strncpy只是简单地按字节拷贝指定长度的内容。其次,如果原字符串的长度大于目的字符串的长度,snprintf会根据指定的size参数来限制拷贝的长度,而strncpy则会按照指定的长度来拷贝,即使目的字符串无法容纳完整的原字符串。此外,在引用中还提到,如果strncpy的源字符串的前n个字符中没有包含null终止符"\0",那么拷贝结果将不会自动加上null终止符。而snprintf会确保目的字符串以null终止。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [snprintfstrcpystrncpy区别](https://blog.youkuaiyun.com/FirMoonLight/article/details/126312445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [strcpystrncpy sprintf和_snprintf区别](https://blog.youkuaiyun.com/weberxian/article/details/3210022)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值