为什么忽略snprintf的'n'参数?


8

我发现我的代码nsnprintf()似乎忽略了参数。

char asdf[10];
Serial1.println(snprintf(asdf, 2, "hello"));

当我希望它能打印2时,它会打印5。发生了什么事?


变量是否asdf包含“ hello”或“ h”?如果它包含“ h”,则该参数未被忽略。
尼克·加蒙

Answers:


7

snprintf()不会向缓冲区中写入超过<size>(snprintf的2d参数)字符,但它会计数(并丢弃多余的)字符,如果有足够的空间,它将写入该字符,这就是它返回的数字。是的,这可能会令人困惑!

请参见此snprintf()参考


5
这将很有帮助,因为您可以snprintf在很小的缓冲区中,记下返回的数字,然后再找到malloc适当大小的缓冲区,然后再做一次。这样,您就知道要分配多少字节。
尼克·加蒙

4
@NickGammon:或者,snprintf在测量长度时,您什么也不能缓存(空目标指针明确描述为destlength == 0情况下的有效参数)。
超级猫

1
确实。Windows文本输出例程中也这样做,以测量某些字体的某些文本将占用多少空间,而无需实际绘制。
尼克·加蒙

3

Arduino Uno的测试草图:

char buffer[10];

void setup() {
  Serial.begin(9600);
  int n = snprintf(buffer, 2, "hello");
  Serial.println(n);
  Serial.println(buffer);
}

void loop() {
}

正如@JRobert所写,“必须”是关键。据我所知,只有snprintfvsnprintf返回一个“将有”数字。

我认为原因是为了能够判断字符串是否被截断。假设'size'参数为25并且格式字符串很长,则可以针对25测试返回值。如果返回值为26(“将具有”字节数),则该字符串将被截断。
当“将有”编号不可用时,无法检索此信息。


2

为了完成,手册页fprintf指出:

snprintf()函数应与sprintf()等效,并增加了n参数,该参数指出s所指缓冲区的大小。如果n为零,则不写任何内容,而s可以为空指针。否则,将丢弃第n-1个字节之后的输出字节,而不是将其写入数组,并且在实际写入数组的字节的末尾写入一个空字节。

并且,更相关:

成功完成后,snprintf()函数应返回n足够大的情况下将写入s的字节数,不包括终止空字节。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.