Die Mehrdeutigkeit geht vom C-Standard selbst aus. Sowohl C99 als auch C11 haben eine identische snprintf
Funktionsbeschreibung. Hier ist die Beschreibung von C99:
7.19.6.5 Die snprintf
Funktion
Synopsis
1 #include <stdio.h>
int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
Beschreibung
2 Die snprintf
Funktion entspricht fprintf
, außer dass die Ausgabe in ein Array (durch Argument angegeben s
) und nicht in einen Stream geschrieben wird. Wenn n
Null ist, wird nichts geschrieben und s
kann ein Nullzeiger sein. Andernfalls werden Ausgabezeichen jenseits von n-1
st verworfen, anstatt in das Array geschrieben zu werden, und am Ende der tatsächlich in das Array geschriebenen Zeichen wird ein Nullzeichen geschrieben. Wenn zwischen überlappenden Objekten kopiert wird, ist das Verhalten undefiniert.
Returns
3 Die snprintf
Funktion gibt die Anzahl der Zeichen , die geschrieben wurden , hätten
ausreichend groß gewesen ist, ohne das abschließende Nullzeichen oder einen negativen Wert, wenn ein Codierungsfehler aufgetreten ist. Daher wurde die nullterminierte Ausgabe genau dann vollständig geschrieben, wenn der zurückgegebene Wert nicht negativ und kleiner als ist n
.
Einerseits der Satz
Andernfalls werden Ausgabezeichen jenseits von n-1
st verworfen, anstatt in das Array geschrieben zu werden, und am Ende der tatsächlich in das Array geschriebenen Zeichen wird ein Nullzeichen geschrieben
sagt, dass
wenn (die s
Punkte auf ein 3 Zeichen langes Array und) n
3 sind, 2 Zeichen geschrieben werden und die Zeichen jenseits des zweiten verworfen werden ; dann wird das Nullzeichen nach diesen 2 geschrieben (und das Nullzeichen ist das 3. geschriebene Zeichen) .
Und das beantwortet meiner Meinung nach die ursprüngliche Frage.
DIE ANTWORT:
Wenn zwischen überlappenden Objekten kopiert wird, ist das Verhalten undefiniert.
Wenn n
0 ist, wird nichts in die Ausgabe geschrieben,
andernfalls wird die Ausgabe IMMER nullterminiert , wenn keine Codierungsfehler aufgetreten sind ( unabhängig davon, ob die Ausgabe in das Ausgabearray passt oder nicht ; wenn nicht, werden einige Zeichen so verworfen, dass die Ausgabe erfolgt Array wird nie überflogen),
andernfalls (wenn Codierungsfehler auftreten) kann die Ausgabe nicht nullterminiert bleiben .
Auf der anderen Seite
Der letzte Satz
Daher wurde die nullterminierte Ausgabe genau dann vollständig geschrieben, wenn der zurückgegebene Wert nicht negativ und kleiner als ist n
gibt Mehrdeutigkeit (oder mein Englisch ist nicht gut genug). Ich kann diesen Satz auf mindestens zwei Arten interpretieren:
1. Die Ausgabe wird genau dann nullterminiert , wenn der zurückgegebene Wert nicht negativ und kleiner als istn
(was bedeutet, dass wenn der zurückgegebene Wert nicht kleiner als ist n
, dh die Ausgabe (einschließlich der) Nullzeichen beenden) passt nicht in das Array, dann ist die Ausgabe nicht nullterminiert ).
2. Die Ausgabe ist genau dann abgeschlossen (es wurden keine Zeichen verworfen), wenn der zurückgegebene Wert nicht negativ und kleiner als istn
.
Ich glaube, dass die obige Interpretation 1 DER ANTWORT widerspricht, Missverständnisse und langwierige Diskussionen hervorruft. Aus diesem Grund muss der letzte Satz, der die snprintf
Funktion beschreibt, geändert werden, um Unklarheiten zu beseitigen (was Anlass gibt, einen Vorschlag für den C-Sprachstandard zu schreiben).
Das Beispiel für eine nicht mehrdeutige Formulierung, von der ich glaube, kann http://en.cppreference.com/w/c/io/fprintf (siehe 4)
) entnommen werden , danke an @ "Martin Ba" für den Link.
Siehe auch die Frage " snprintf: Gibt es C-Standardvorschläge / Pläne zur Änderung der Beschreibung dieser Funktion? ".