Perché il parametro 'n' di snprintf viene ignorato?


8

Ho scoperto che il nparametro di snprintf()sembra essere ignorato nel mio codice.

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

Questo stampa 5 quando mi aspetto che stampi 2. Cosa sta succedendo?


La variabile asdfcontiene "ciao" o "h"? Se contiene "h", il parametro non è stato ignorato.
Nick Gammon

Risposte:


7

snprintf () non scriverà più di <size> (secondo argomento di snprintf) caratteri nel buffer, ma conta (e scarta gli extra) che avrebbe scritto, se ci fosse stato abbastanza spazio, e questo è il numero che restituisce . Sì, può essere fonte di confusione!

Vedi questo riferimento snprintf () .


5
Sarebbe utile perché potresti utilizzare snprintfun buffer molto piccolo, annotare il numero restituito, quindi mallocun buffer della dimensione appropriata e farlo di nuovo. In questo modo sai quanti byte assegnare.
Nick Gammon

4
@NickGammon: oppure non è possibile snprintfbufferizzare in alcun modo (un puntatore di destinazione null viene esplicitamente descritto come argomento valido per il caso destlength == 0) quando si misura la lunghezza.
supercat,

1
Infatti. Questo viene fatto anche nelle routine di output del testo di Windows per misurare la quantità di spazio che il testo in alcuni font occuperebbe, senza effettivamente disegnarlo.
Nick Gammon

3

Uno schizzo di prova per Arduino Uno:

char buffer[10];

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

void loop() {
}

Come ha scritto @JRobert, il "avrebbe" è la chiave. Per quanto ne so solo snprintf e vsnprintf restituiscono un numero "avrebbe".

Penso che il motivo sia quello di poter dire se la stringa è stata troncata. Supponiamo che il parametro 'size' sia 25 e che la stringa di formato sia molto lunga, quindi il valore di ritorno può essere testato rispetto a 25. Se il valore di ritorno era 26 (il "avrebbe" numero di byte), allora la stringa veniva troncata.
Non è stato possibile recuperare queste informazioni quando il numero "avrebbe" non era disponibile.


2

Per il completamento, la pagina man per gli fprintfstati:

La funzione snprintf () deve essere equivalente a sprintf (), con l'aggiunta dell'argomento n che indica la dimensione del buffer a cui fa riferimento s. Se n è zero, nulla deve essere scritto e s può essere un puntatore nullo. Altrimenti, i byte di output oltre il n-1 devono essere eliminati anziché essere scritti nell'array e un byte null viene scritto alla fine dei byte effettivamente scritti nell'array.

e, più pertinente:

In caso di completamento con esito positivo, la funzione snprintf () deve restituire il numero di byte che verrebbero scritti in s se non fosse stato sufficientemente grande, escluso il byte null terminante.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.