0

根据我对 C 标准的阅读,如果在写入时snprinf达到maxlen,它将返回一个正值或负值(实际上并不清楚),其大小等于未能写入的字符数。规范还说,该函数将为任何错误返回负值。所以我的问题是:在以下两种情况下它会返回什么......

Maxlen > 0, 在发生错误并snprintf退出之前不写入任何字符

Maxlen > 0,所有字符都被写入,出现某种错误并snprintf退出

我意识到最后一个,特别是不太可能。但我想更好地理解规范。在我看来,snprintf 的返回使您是否正确编写了字符串的一部分变得模棱两可。

        • 编辑

显然这并不清楚。让我详细说明:

*> 哪个负数无关紧要。错误就是错误,它不是

无论在发生之前写入了多少字节。这可能是大多数人的实际情况。但是,我看到 snprintf 应该返回多余字符的数量,我想知道是否可以使用该值。对我来说,规范会遇到麻烦报告一些有用的东西,这对我来说似乎很奇怪,只是让它模棱两可,它是否真的返回了一些不相关的东西。这没有意义吗?我想知道约定是否有更多内容可以确定 snprintf 是否因为输入过多而失败。*

我现在明白了。我看到除截断以外的任何错误都是负数,成功是 0 < R <= maxsize,截断是 0 < maxsize < R。感谢所有回复的人。

4

4 回答 4

2

这不是我阅读标准的方式。来自 n1570 草案(我认为是最终免费的):

snprintf 函数返回如果 n 足够大,将写入的字符数,不包括终止的空字符,或者如果发生编码错误,则返回负值。因此,当且仅当返回值为非负且小于 n 时,以空值结尾的输出已被完全写入。

他们的原型是:

int sprintf(char * restrict s, const char * restrict format, ...);

...所以他们的“n”大概是你的“Maxlen”值。

所以,没有问题。如果出现错误,您会得到 -42 或其他任意负数。如果没有,您将获得要写入的所有数据的长度。适合的部分被写入缓冲区,如果返回值大于或等于 ,则被截断n

我看到的唯一未指定的一点是,由于n是 a size_t,因此结果可能大于适合正 int 返回值的值。不过,我想不出会受此影响的应用程序。

于 2013-10-05T19:00:13.410 回答
1

我想知道约定是否有更多内容可以确定 snprintf 是否因为输入过多而失败。

这很简单。对于错误,返回负数。对于截断,返回一个 >= 大小的数字。无论您是否将截断视为错误,您都可以测试这两个条件并按您认为合适的方式处理。

于 2013-10-05T18:51:43.297 回答
0

手册页中的描述:

返回值

成功返回后,这些函数返回打印的字符数(不包括用于结束输出到字符串的空字节)。

函数 snprintf() 和 vsnprintf() 写入的字节数不超过 size 字节(包括终止的空字节 ('\0'))。如果输出由于此限制而被截断,则返回值是字符数(不包括终止的空字节),如果有足够的空间可用,这些字符将被写入最终字符串。因此,大小或更大的返回值意味着输出被截断。(另请参阅下面的注释。)

如果遇到输出错误,则返回负值。

所以对于你的情况:

Maxlen > 0, 在发生错误并snprintf退出之前不写入任何字符

snprintf返回一个负数。哪个负数无关紧要。

Maxlen > 0,所有字符都被写入,发生某种错误并且 snprintf 保释

snprintf返回一个负数。哪个负数无关紧要。错误就是错误,在它发生之前写入了多少字节都没有关系。

于 2013-10-05T18:26:56.910 回答
0

作为进一步的评论,当重复使用 snprintf 以增量方式构建字符串时(例如在循环中) - 或者必须确定结果字符串长度的任何地方,我建议这是一种“安全”的方法......

int foo( char * b, size_t bLen ) {
  size_t sLen = 0;
  for(int i = 0; i < 1000; i++) {
    int res = snprintf(&b[sLen], bLen - sLen, "%d. A string ", sLen);
    // sLen:         Inc by +ive res,      (upto safe maximum)        
    sLen = std::min( sLen + (res>0?res:0), (bLen?bLen-1:bLen) );
  }
  return sLen;
}

snprintf 之后的行将安全地增加字符串长度变量 (sLen),忽略负结果 (res) 并通过限制缓冲区长度 (bLen) 来防止溢出。我在示例中使用了 C++“min”,但堆栈溢出提供了“C”替代方案:C中的 MIN 和 MAX

于 2015-02-03T09:54:31.433 回答