Warum wird der Parameter 'n' von snprintf ignoriert?

8

Ich habe festgestellt, dass der nParameter von snprintf()in meinem Code ignoriert zu werden scheint.

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

Dies druckt 5, wenn ich erwarten würde, dass es 2 druckt. Was passiert?

Westin
quelle
Enthält die Variable asdf"Hallo" oder "h"? Wenn es "h" enthält, wurde der Parameter nicht ignoriert.
Nick Gammon

Antworten:

7

snprintf () schreibt nicht mehr als <Größe> (2d-Argument von snprintf) in Ihren Puffer, zählt jedoch die zusätzlichen Zeichen (und verwirft sie), die es geschrieben hätte, wenn genügend Platz vorhanden wäre, und das ist die zurückgegebene Zahl . Ja, das kann verwirrend sein!

Siehe diese snprintf () Referenz .

JRobert
quelle
5
Dies wäre hilfreich, da Sie snprintfin einem sehr kleinen Puffer die zurückgegebene Nummer und dann malloceinen Puffer der entsprechenden Größe notieren und erneut ausführen könnten . Auf diese Weise wissen Sie, wie viele Bytes zugewiesen werden müssen.
Nick Gammon
4
@NickGammon: Oder Sie können snprintfbeim Messen der Länge keinen Puffer verwenden (ein Null-Zielzeiger wird explizit als gültiges Argument für den Fall destlength == 0 beschrieben).
Supercat
1
Tatsächlich. Dies wird auch in Windows-Textausgaberoutinen durchgeführt, um zu messen, wie viel Platz ein Text in einer Schriftart einnehmen würde, ohne ihn tatsächlich zu zeichnen.
Nick Gammon
3

Eine Testskizze für den Arduino Uno:

char buffer[10];

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

void loop() {
}

Wie @JRobert schrieb, ist das "hätte" der Schlüssel. Soweit ich weiß, geben nur snprintf und vsnprintf eine "hätte" -Nummer zurück.

Ich denke, der Grund ist, feststellen zu können, ob die Zeichenfolge abgeschnitten wurde. Angenommen, der Parameter 'size' ist 25 und die Formatzeichenfolge ist sehr lang, dann kann der Rückgabewert gegen 25 getestet werden. Wenn der Rückgabewert 26 war (die Anzahl der Bytes "hätte"), wurde die Zeichenfolge abgeschnitten.
Diese Informationen konnten nicht abgerufen werden, wenn die "hätte" -Nummer nicht verfügbar war.

Jot
quelle
2

Zum Abschluss der Manpage für fprintfZustände:

Die Funktion snprintf () muss sprintf () entsprechen, wobei das Argument n hinzugefügt wird, das die Größe des Puffers angibt, auf den sich s bezieht. Wenn n Null ist, darf nichts geschrieben werden und s kann ein Nullzeiger sein. Andernfalls werden Ausgabebytes jenseits des n-1 verworfen, anstatt in das Array geschrieben zu werden, und am Ende der tatsächlich in das Array geschriebenen Bytes wird ein Nullbyte geschrieben.

und relevanter:

Nach erfolgreichem Abschluss gibt die Funktion snprintf () die Anzahl der Bytes zurück, die in s geschrieben würden, wenn n ohne das abschließende Nullbyte ausreichend groß gewesen wäre.

Greenonline
quelle