gpt4 book ai didi

c - snprintf 用于组成格式化字符串的用法

转载 作者:行者123 更新时间:2023-12-01 08:03:20 29 4
gpt4 key购买 nike

我正在尝试了解 snprintf 并找到了 this answer举个例子:

char buf[20] = "";
char *cur = buf, * const end = buf + sizeof buf;
cur += snprintf(cur, end-cur, "%s", "foo");
printf("%s\n", buf);
if (cur < end) {
cur += snprintf(cur, end-cur, "%s", " bar");
}
printf("%s\n", buf);
free(str);

我不清楚的是,我们分配了一个固定的硬编码缓冲区大小,这似乎受到缓冲区溢出的影响。在 N1570 中我发现 (7.21.6.5)

1

#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);

2 The snprintf function is equivalent to fprintf, except that the output is written into an array (specified by argument s) rather than to a stream. If n is zero, nothing is written, and s may be a null pointer.

所以在我看来,惯用用法如下:

int need_space = snprintf(NULL, 0, "abs %s", "fgh") + 1; //How much to allocate?
char *const str = malloc(need_space * sizeof(char)); //allocate
int written = snprintf(str, need_space, "abs %s", "fgh"); //do format
printf("Need space = %d, written = %d\n", need_space, written);
printf("%s\n", str);

或者这不常见并且有其他问题?

最佳答案

snprintf() 的 2x 调用是一个常见的习惯用法。

... has another problem?

问题在角落

格式维护

下面的格式重复 - 容易随着代码老化而中断,并且只有一行被更改。

// Oops!
int need_space = snprintf(NULL, 0, "abs %s", "fgh") + 1;
char *const str = malloc(need_space * sizeof(char));
int written = snprintf(str, need_space, "abs %s ", "fgh");

你注意到区别了吗?

最好一次声明格式。

#define FMT_ABS_S "abs %s"
int need_space = snprintf(NULL, 0, FMT_ABS_S, "fgh");
char *const str = malloc(sizeof *str * (need_space + 1u));
int written = snprintf(str, need_space, FMT_ABS_S, "fgh");

波动性

代码需要确保值在两次调用之间不会发生变化(非volatile),在多线程应用程序中会出现特殊问题。

错误检查

代码缺少检查。然而,即使有支票,如何处理意想不到的结果——也许只是保释?

static const char *fmt_s = "abs %s";
int needed_space = snprintf(NULL, 0, fmt_s, "fgh");
if (needed_space < 0) {
Handle_EncodingError();
}
char * const str = malloc(sizeof *str * (needed_space + 1u));
if (str == NULL) {
Handle_OutOfMemory();
}
int written = snprintf(str, needed_space, fmt_s, "fgh");
if (written < 0 || written > needed_space) {
Handle_Error();
}

尽管去两次

2 次调用在特定情况下可能会造成浪费,但通常影响比想象的要小。 @Jonathan Leffler

然而对我来说,“如果分配失败该怎么办”无论如何都是一个障碍,代码会报告错误并可能退出。

有选择性,一次就够

s*printf() 格式受到严格控制时,我认为调用 1 次就足够了。

// int to string

#define LOG2_N 28
#define LOG2_D 93
// Number of char needed for a string of INT_MIN is log10(bit width) + 3
#define INT_SIZE ((sizeof(int)*CHAR_BIT-1)*LOG2_N/LOG2_D + 3)

char s[INT_SIZE * 2]; // I like to use 2x to handle locale issues, no need to be stingy here.

int len = snprintf(s, sizeof s, "%d", i);

if (len < 0 || (unsigned) len >= sizeof s) {
Handle_VeryUnusualFailure();
}

关于c - snprintf 用于组成格式化字符串的用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54211886/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com