0%

sprintf 和 snprintf 的正确使用

我们经常使用 sprintfsnprintf 格式化输出一些字串到指定buffer,但许多同学不知道这两个函数具体作用以及到底有什么区别,在这里我们通过一些测试用例来具体分析一下。

基本代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void test_sprintf_and_snprintf()
{
#define MAX_LEN (15)
#define ARR_LEN (10)

// 0 ~ 9 测试buffer, 10 ~ 14 预留buffer, 用于演示溢出
char array[MAX_LEN];
// sprintf、snprintf的返回值
u16 result_len = 0;

// 字串长度小于buffer长度
memset(array, 0xFF, MAX_LEN);
result_len = sprintf(array, "%s", "12345");
memset(array, 0xFF, MAX_LEN);
result_len = snprintf(array, ARR_LEN, "%s", "12345");

// 字串长度等于buffer长度
memset(array, 0xFF, MAX_LEN);
result_len = sprintf(array, "%-10s", "12345");
memset(array, 0xFF, MAX_LEN);
result_len = snprintf(array, ARR_LEN, "%-10s", "12345");

// 字串长度大于buffer长度
memset(array, 0xFF, MAX_LEN);
result_len = sprintf(array, "%s", "123456789AB");
memset(array, 0xFF, MAX_LEN);
result_len = snprintf(array, ARR_LEN, "%s", "123456789AB");

// 数字长度等于buffer长度
memset(array, 0xFF, MAX_LEN);
result_len = sprintf(array, "%d", 2147483645);
memset(array, 0xFF, MAX_LEN);
result_len = snprintf(array, ARR_LEN, "%d", 2147483647);
}

测试结果

我们在每次测试前,都将array中的数据初始化为0xFF,这样我们可以很方便的观测到数据变化,测试结果如下,箭头指示着测试buffer的结束位置,还请注意0x00在哪里:

1
2
3
4
5
6
7
8
// 字串长度小于buffer长度
sprintf(array, "%s", "12345"); ↓
0x31 0x32 0x33 0x34 0x35 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
result_len = 5

snprintf(array, ARR_LEN, "%s", "12345"); ↓
0x31 0x32 0x33 0x34 0x35 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
result_len = 5
1
2
3
4
5
6
7
8
// 字串长度等于buffer长度
sprintf(array, "%-10s", "12345"); ↓
0x31 0x32 0x33 0x34 0x35 0x20 0x20 0x20 0x20 0x20 0x00 0xff 0xff 0xff 0xff
result_len = 10

snprintf(array, ARR_LEN, "%-10s", "12345"); ↓
0x31 0x32 0x33 0x34 0x35 0x20 0x20 0x20 0x20 0x00 0xff 0xff 0xff 0xff 0xff
result_len = 10
1
2
3
4
5
6
7
8
// 字串长度大于buffer长度
sprintf(array, "%s", "123456789AB"); ↓
0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x41 0x42 0x00 0xff 0xff 0xff
result_len = 11

snprintf(array, ARR_LEN, "%s", "123456789AB"); ↓
0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x00 0xff 0xff 0xff 0xff 0xff
result_len = 11
1
2
3
4
5
6
7
8
// 数字长度等于buffer长度
sprintf(array, "%d", 2147483645); ↓
0x32 0x31 0x34 0x37 0x34 0x38 0x33 0x36 0x34 0x35 0x00 0xff 0xff 0xff 0xff
result_len = 10

snprintf(array, ARR_LEN, "%d", "2147483647"); ↓
0x32 0x31 0x34 0x37 0x34 0x38 0x33 0x36 0x34 0x00 0xff 0xff 0xff 0xff 0xff
result_len = 10

测试结论

sprintf snprintf
以’\0’结尾? Y Y
字串有可能被截断? N Y
可能溢出? Y N
输出到buffer的长度 (字串长度 + 1) (字串长度 + 1)、限制长度中取较小的
返回值 字串长度 字串长度