Pourquoi le paramètre 'n' de snprintf est-il ignoré?

8

J'ai trouvé que le nparamètre de snprintf()semble être ignoré dans mon code.

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

Cela imprime 5 quand je m'attendrais à ce qu'il imprime 2. Que se passe-t-il?

Westin
la source
La variable asdfcontient-elle "bonjour" ou "h"? S'il contient "h", le paramètre n'a pas été ignoré.
Nick Gammon

Réponses:

7

snprintf () n'écrira pas plus de <size> (argument 2d de snprintf) dans votre tampon, mais il compte (et supprime les caractères supplémentaires) qu'il aurait écrits, s'il y avait eu suffisamment d'espace, et c'est le nombre qu'il renvoie . Ouais, ça peut être déroutant!

Voir cette référence snprintf () .

JRobert
la source
5
Il serait utile car vous pouvez utiliser snprintfun très petit tampon, noter le nombre renvoyé, puis mallocun tampon de la taille appropriée et recommencer. De cette façon, vous savez combien d'octets allouer.
Nick Gammon
4
@NickGammon: Ou vous ne pouvez utiliser snprintfaucun tampon (un pointeur de destination nul est explicitement décrit comme un argument valide pour le cas destlength == 0) lors de la mesure de la longueur.
supercat
1
En effet. Cela se fait également dans les routines de sortie de texte Windows pour mesurer la quantité d'espace qu'un texte dans une police occuperait, sans le dessiner.
Nick Gammon
3

Un croquis de test pour l'Arduino Uno:

char buffer[10];

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

void loop() {
}

Comme l'a écrit @JRobert, «l'aurait» est la clé. Pour autant que je sache, seuls le snprintf et le vsnprintf renvoient un numéro "aurait".

Je pense que la raison est de pouvoir dire si la chaîne a été tronquée. Supposons que le paramètre 'size' soit 25 et que la chaîne de formatage soit très longue, la valeur de retour peut être testée par rapport à 25. Si la valeur de retour était 26 (le nombre "aurait" d'octets), alors la chaîne a été tronquée.
Cette information n'a pas pu être récupérée lorsque le numéro "aurait" n'était pas disponible.

Iota
la source
2

Pour terminer, la page de manuel des fprintfétats:

La fonction snprintf () doit être équivalente à sprintf (), avec l'ajout de l'argument n qui indique la taille du tampon mentionné par s. Si n est nul, rien ne sera écrit et s peut être un pointeur nul. Sinon, les octets de sortie au-delà du n-1er doivent être ignorés au lieu d'être écrits dans le tableau, et un octet nul est écrit à la fin des octets réellement écrits dans le tableau.

et, plus pertinent:

En cas de réussite, la fonction snprintf () doit retourner le nombre d'octets qui seraient écrits dans s si n était suffisamment grand à l'exclusion de l'octet nul final.

Greenonline
la source