snprintfの「n」パラメーターが無視されるのはなぜですか?


8

nパラメーターがsnprintf()コードで無視されているようです。

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

これは、2を印刷すると予想されるときに5を印刷します。


変数asdfに「hello」または「h」が含まれていますか?「h」が含まれている場合、パラメーターは無視されていません。
Nick Gammon

回答:


7

snprintf()は、バッファに<size>(snprintfの2d引数)より多くの文字を書き込みませんが、十分なスペースがあり、返される数値である場合、書き込まれた文字を数えます(そして余分な文字を破棄します) 。ええ、それは混乱する可能性があります!

このsnprintf()リファレンスを参照してください


5
snprintf非常に小さなバッファに戻り、返された数を記録してmallocから、適切なサイズのバッファを記録して、それを再度実行できるので、役に立ちます。これにより、割り当てるバイト数がわかります。
Nick Gammon

4
@NickGammon:またはsnprintf、長さを測定するときに、バッファなしにすることもできます(nest 宛先ポインタは、destlength == 0の場合の有効な引数として明示的に説明されています)。
スーパーキャット2018年

1
確かに。Windowsのテキスト出力ルーチンでも、実際に描画せずに、フォント内のテキストが占めるスペースを測定します。
Nick Gammon

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()と同等であり、sによって参照されるバッファーのサイズを示すn引数が追加されます。nがゼロの場合、何も書き込まれず、sはnullポインターになる場合があります。それ以外の場合、n-1番目を超える出力バイトは、配列に書き込まれるのではなく破棄され、実際に配列に書き込まれるバイトの最後にnullバイトが書き込まれます。

そして、より関連性の高い:

正常に完了すると、snprintf()関数は、終端のnullバイトを除いてsに書き込まれるバイト数が十分に大きかった場合に、それを返します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.