如果在maxlen>中没有写任何内容,snprintf会返回什么? 0?

时间:2013-10-05 18:17:01

标签: c printf

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

Maxlen > 0,在发生错误并且snprintf保释

之前不会写入任何字符

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

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

        • 修改

显然这还不清楚。让我详细说明一下:

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

  

在发生之前写入了多少字节。   这可能是大多数人的实际案例。我看到snprintf应该返回多余字符的数量,但是,我想知道是否可以使用该值。   对我来说,这个规范会报告一些有用的东西,只是为了让它变得模糊不清,以确定它是否真的回归了一些无关紧要的东西。这没有意义吗?   我想知道是否有更多的约定可以确定snprintf是否因为输入太多而失败。*

我现在明白了。我看到除了截断之外的任何错误都是否定的,成功是0&lt; R&lt; = maxsize,截断为0 <0。 maxsize&lt;谢谢所有回复的人。

4 个答案:

答案 0 :(得分:2)

这不是我读标准的方式。从n1570草案(最后一个,我认为):

  

snprintf函数返回可能包含的字符数   写得已经足够大了,不算数了   如果编码错误,则终止空字符或否定值   发生了。因此,完全写入了以null结尾的输出   当且仅当返回的值是非负且小于n时才<。

他们的原型是:

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

...所以他们的“n”可能是你的“Maxlen”值。

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

我看到的唯一未指定的位是因为nsize_t,所以结果可能大于适合正int返回值。不过,我想不出会受到影响的应用程序。

答案 1 :(得分:1)

  

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

这很简单。对于错误,返回负数。对于截断,返回数字> = = size。无论您是否考虑截断错误,都可以根据需要测试这两种情况并进行处理。

答案 2 :(得分:0)

man page

中的说明
  

返回值

     

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

     

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

     

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

所以对你的情况来说:

  

Maxlen > 0,在发生错误并且snprintf保释

之前不会写入任何字符

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

  

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

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

答案 3 :(得分:0)

作为进一步的评论,当重复使用snprintf来逐步构建字符串时(例如在循环内) - 或者必须确定结果字符串长度的任何地方,我建议将其作为一个&#34; safe&#34;方法...

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 ++&#34; min&#34;在我的例子中,但是堆栈溢出提供了C&#39;替代方案:MIN and MAX in C