C 如何确定真正需要的字符数组的大小?

C 如何确定真正需要的字符数组的大小?,c,arrays,printf,C,Arrays,Printf,我对以下代码有一个问题: void testing(int idNumber) { char name[20]; snprintf(name, sizeof(name), "number_%d", idNumber); } 字符数组name的大小是20,因此如果idNumber是111它可以工作,但是实际的idNumber是111111111111111111,如何确定字符数组的大小以保持snprintf的结果?查看snprintf的文档。如果目标传递NULL,大小传递0,它

我对以下代码有一个问题:

void testing(int idNumber)
{
    char name[20];

    snprintf(name, sizeof(name), "number_%d", idNumber);
}

字符数组
name
的大小是20,因此如果
idNumber
111
它可以工作,但是实际的idNumber是
111111111111111111
,如何确定字符数组的大小以保持
snprintf
的结果?

查看snprintf的文档。如果目标传递NULL,大小传递0,它将返回所需的字节数。因此,首先,对内存进行malloc,然后使用正确的大小执行另一个snprintf


所有printf函数都返回打印的字节数(不包括尾随的零),但snprintf将返回在长度不受限制的情况下打印的字符数

查看snprintf的文档。如果目标传递NULL,大小传递0,它将返回所需的字节数。因此,首先,对内存进行malloc,然后使用正确的大小执行另一个snprintf


所有printf函数都返回打印的字节数(不包括尾随的零),但snprintf将返回在长度不受限制的情况下打印的字符数

只有一个好答案:
询问
snprintf
本身(传递长度0)

它返回如果缓冲区足够大,它将写入的输出大小,不包括终止的0

标准报价(C99+修订版):

7.21.6.5 snprintf功能 概要

#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);
#包括
int snprintf(字符*限制s,大小\u t n,
常量字符*限制格式,…);
说明
2
snprintf
功能等同于
fprintf
,只是输出写入 数组(由参数
s
指定)而不是流。如果
n
为零,则不写入任何内容, 而
s
可能是空指针。否则,超出
n-1
st的输出字符将被删除 丢弃而不是写入数组,并在末尾写入空字符 实际写入数组的字符数。如果复制发生在对象之间 如果重叠,则行为未定义。
返回值
3
snprintf
函数返回本应写入的字符数
n
是否足够大,不包括终止的空字符或负数 值(如果发生编码错误)。因此,空终止的输出已被删除 完全写入当且仅当返回值为非负且小于
n


只有一个好答案:
询问
snprintf
本身(传递长度0)

它返回如果缓冲区足够大,它将写入的输出大小,不包括终止的0

标准报价(C99+修订版):

7.21.6.5 snprintf功能 概要

#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);
#包括
int snprintf(字符*限制s,大小\u t n,
常量字符*限制格式,…);
说明
2
snprintf
功能等同于
fprintf
,只是输出写入 数组(由参数
s
指定)而不是流。如果
n
为零,则不写入任何内容, 而
s
可能是空指针。否则,超出
n-1
st的输出字符将被删除 丢弃而不是写入数组,并在末尾写入空字符 实际写入数组的字符数。如果复制发生在对象之间 如果重叠,则行为未定义。
返回值
3
snprintf
函数返回本应写入的字符数
n
是否足够大,不包括终止的空字符或负数 值(如果发生编码错误)。因此,空终止的输出已被删除 完全写入当且仅当返回值为非负且小于
n


好的,如果您的平台上的
int
是32位,那么它可以打印的最宽值将是-20亿,即11个字符,因此
数字需要7个字符,
%d
需要11个字符,空终止符需要1个字符,总共需要19个字符


但是您通常应该检查
snprintf()
中的返回值,以确保有足够的空间。例如,如果将“locale”设置为标准的“C”字符以外的其他字符,则它可以打印数千个分隔符,在这种情况下,您需要比现有字符多2个。

好吧,如果
int
在您的平台上是32位,那么它可以打印的最宽值将是-20亿,即11个字符,因此,您需要7个用于
编号
,11个用于
%d
,1个用于空终止符,总共19个

但是您通常应该检查
snprintf()
中的返回值,以确保有足够的空间。例如,如果“locale”设置为标准“C”以外的其他字符,则它可能会打印数千个分隔符,在这种情况下,您需要比现有字符多2个字符。

引用自:

如果生成的字符串长度超过n-1个字符,则 剩余的字符将被丢弃且不存储,但会被计算为 函数返回的值

引自:

如果生成的字符串长度超过n-1个字符,则 剩余的字符将被丢弃且不存储,但会被计算为 函数返回的值


要使用大小合适的缓冲区,请计算其最大需要量

#define INT_PRINT_SIZE(i) ((sizeof(i) * CHAR_BIT)/3 + 3)

void testing(int idNumber) {
  const char format[] = "number_%d";
  char name[sizeof format + INT_PRINT_SIZE(idNumber)];
  snprintf(name, sizeof(name), format, idNumber);
}
这种方法假设C语言环境。可以使用一个更健壮的解决方案

  ...
  int cnt = snprintf(name, sizeof(name), format, idNumber);
  if (cnt < 0 || cnt >= sizeof(name)) Handle_EncodingError_SurprisingLocale().
。。。
int cnt=snprintf(名称、大小(名称)、格式、idNumber);
如果(cnt<0 | | cnt>=sizeof(name))处理编码错误。

类似于要使用大小合适的缓冲区,请计算