众所周知,sprintf不能检查目标字符串的长度,可能造成众多安全问题,所以都会推荐使用snprintf.
自从snprintf代替了sprintf,相信大家对snprintf的使用都不会少,函数定义如下:
int snprintf(char*str, size_t size,constchar*format, ...);
函数说明:最多从源串中拷贝size-1个字符到目标串中,然后再在后面加一个 \0 。所以如果目标串的大小为size的话,将不会溢出。
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。
Result1(推荐的用法)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[10]={0};
snprintf(str, sizeof(str), "0123456789012345678");
printf("str=%s\r\n", str);
return 0;
}
root] /root/lindatest
$ ./test
str=012345678
Result2:(不推荐使用)
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[10]={0};
snprintf(str, 18, "0123456789012345678");
printf("str=%s\r\n", str);
return 0;
}
root] /root/lindatest
$ ./test
str=01234567890123456
【情形一】:源串小于目标字符串
实际上源串为:"123\0",所以只将字符'1','2','3', '\0'拷到了目标串,返回值为源串的strlen为3
#include <stdio.h>
#include <strings.h>
#include <string.h>
int main(void)
{
char a[10] = {'\0'};
int i = 0;
int ret = 0;
memset(a, 0, sizeof(a));
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
ret = snprintf(a, 10, "%d", 123);
printf("ret = %d\n",ret);
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
a[0] = 0
a[1] = 0
a[2] = 0
a[3] = 0
a[4] = 0
a[5] = 0
a[6] = 0
a[7] = 0
a[8] = 0
a[9] = 0
ret = 3
a[0] = 49
a[1] = 50
a[2] = 51
a[3] = 0
a[4] = 0
a[5] = 0
a[6] = 0
a[7] = 0
a[8] = 0
a[9] = 0
--------------------------------
Process exited after 0.1323 seconds with return value 0
请按任意键继续. . .
【情形二】:源串等于目标字符串
源串为"abcdefghi\0",正好将源串拷贝到目标字符串中,返回值为源串的strlen为9
#include <stdio.h>
#include <strings.h>
#include <string.h>
int main(void)
{
char a[10] = {'\0'};
int i = 0;
int ret = 0;
memset(a, 0, sizeof(a));
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
ret = snprintf(a, 10, "%s","abcdefghi");
printf("ret = %d\n",ret);
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
a[0] = 0
a[1] = 0
a[2] = 0
a[3] = 0
a[4] = 0
a[5] = 0
a[6] = 0
a[7] = 0
a[8] = 0
a[9] = 0
ret = 9
a[0] = 97
a[1] = 98
a[2] = 99
a[3] = 100
a[4] = 101
a[5] = 102
a[6] = 103
a[7] = 104
a[8] = 105
a[9] = 0
--------------------------------
Process exited after 0.3018 seconds with return value 0
请按任意键继续. . .
【情形三】源串大于目标字符串
源串为"abcdefghijklmnopq\0",最多从源串拷贝10个字节(含\0)到目标串那么就是拷贝源串的9个字节内容(abcdefghi)再加一个\0到目标串,目标串的结果和情形二一样,但是ret返回值变成了17,即strlen("abcdefghijklmnopq")
#include <stdio.h>
#include <strings.h>
#include <string.h>
int main(void)
{
char a[10] = {'\0'};
int i = 0;
int ret = 0;
memset(a, 0, sizeof(a));
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
ret = snprintf(a, 10, "%s", "abcdefghijklmnopq");
printf("ret = %d\n",ret);
for(i = 0; i < 10; i++) {
printf("a[%d] = %d\n",i,a[i]);
}
return 0;
}
在VC中编译如下程序:
a[0] = 0
a[1] = 0
a[2] = 0
a[3] = 0
a[4] = 0
a[5] = 0
a[6] = 0
a[7] = 0
a[8] = 0
a[9] = 0
ret = -1
a[0] = 97
a[1] = 98
a[2] = 99
a[3] = 100
a[4] = 101
a[5] = 102
a[6] = 103
a[7] = 104
a[8] = 105
a[9] = 106
--------------------------------
Process exited after 0.02983 seconds with return value 0
请按任意键继续. . .
在GCC中编译如下程序:
a[0] = 0
a[1] = 0
a[2] = 0
a[3] = 0
a[4] = 0
a[5] = 0
a[6] = 0
a[7] = 0
a[8] = 0
a[9] = 0
ret = 17
a[0] = 97
a[1] = 98
a[2] = 99
a[3] = 100
a[4] = 101
a[5] = 102
a[6] = 103
a[7] = 104
a[8] = 105
a[9] = 106
--------------------------------
Process exited after 0.02983 seconds with return value 0
请按任意键继续. . .
snprintf打印16进制
snprintf(temp, sizeof temp, "%X", USART_RX_BUF[0]);
%02x 格式控制: 以十六进制输出,2为指定的输出字段的宽度.如果位数小于2,则左端补0
如果USART_RX_BUF[0]里的数据是0xf8,
snprintf(temp, sizeof temp, "%X", USART_RX_BUF[0]);
temp[0]的值为0x46;
temp[1]的值为0x38;
参考:https://blog.csdn.net/liaojunwu/article/details/80489406
参考:https://blog.csdn.net/sky1203850702/article/details/52778831
参考:https://blog.csdn.net/shenhuxi_yu/article/details/70195133