根据我对C标准的阅读,如果snprinf
在写作时达到maxlen
,它将返回正值或负值(实际上并不清楚),其大小与数字相等无法写入的字符。规范还说该函数将为任何错误返回负值。所以我的问题是:在以下两种情况下它会返回什么......
Maxlen > 0
,在发生错误并且snprintf
保释
Maxlen > 0
,所有字符都被写入,出现某种错误,snprintf
保释
我意识到最后一个,特别是不太可能。但我想更好地理解规范。在我看来,无论你是否正确地写了一部分字符串,snprintf的返回都会使它变得模棱两可。
显然这还不清楚。让我详细说明一下:
* GT;哪个负数无关紧要。错误是错误,它不是
在发生之前写入了多少字节。 这可能是大多数人的实际案例。我看到snprintf应该返回多余字符的数量,但是,我想知道是否可以使用该值。 对我来说,这个规范会报告一些有用的东西,只是为了让它变得模糊不清,以确定它是否真的回归了一些无关紧要的东西。这没有意义吗? 我想知道是否有更多的约定可以确定snprintf是否因为输入太多而失败。*
我现在明白了。我看到除了截断之外的任何错误都是否定的,成功是0&lt; R&lt; = maxsize,截断为0 <0。 maxsize&lt;谢谢所有回复的人。
答案 0 :(得分:2)
这不是我读标准的方式。从n1570草案(最后一个,我认为):
snprintf函数返回可能包含的字符数 写得已经足够大了,不算数了 如果编码错误,则终止空字符或否定值 发生了。因此,完全写入了以null结尾的输出 当且仅当返回的值是非负且小于n时才<。
他们的原型是:
int sprintf(char * restrict s, const char * restrict format, ...);
...所以他们的“n”可能是你的“Maxlen”值。
所以,没有问题。如果出现错误,您会得到-42或其他任意负数。如果没有,您将获得要写入的所有数据的长度。适合的部分写入缓冲区,如果返回值大于或等于n
,则会发生截断。
我看到的唯一未指定的位是因为n
是size_t
,所以结果可能大于适合正int返回值。不过,我想不出会受到影响的应用程序。
答案 1 :(得分:1)
我想知道是否有更多的约定可以确定snprintf是否因为输入太多而失败。
这很简单。对于错误,返回负数。对于截断,返回数字> = = size。无论您是否考虑截断错误,都可以根据需要测试这两种情况并进行处理。
答案 2 :(得分:0)
返回值
成功返回后,这些函数返回打印的字符数(不包括用于结束输出到字符串的空字节)。
函数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