¿Por qué se ignora el parámetro 'n' de snprintf?


8

He encontrado que el nparámetro de snprintf()parece ser ignorado en mi código.

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

Esto imprime 5 cuando esperaría que imprimiera 2. ¿Qué está pasando?


¿La variable asdfcontiene "hola" o "h"? Si contiene "h", entonces el parámetro no ha sido ignorado.
Nick Gammon

Respuestas:


7

snprintf () no escribirá más que caracteres <size> (argumento 2d de snprintf) en su búfer, pero sí cuenta (y descarta) los caracteres adicionales que hubiera escrito, si hubiera habido espacio suficiente, y ese es el número que devuelve . ¡Sí, puede ser confuso!

Consulte esta referencia de snprintf () .


55
Sería útil porque podría snprintfhacer un búfer muy pequeño, anotar el número devuelto, luego mallocun búfer del tamaño apropiado y volver a hacerlo. De esa manera, usted sabe cuántos bytes asignar.
Nick Gammon

44
@NickGammon: O no puede snprintfalmacenar ningún búfer (un puntero de destino nulo se describe explícitamente como un argumento válido para el caso destlength == 0) al medir la longitud.
supercat

1
En efecto. Eso también se hace en las rutinas de salida de texto de Windows para medir cuánto espacio ocuparía un texto en alguna fuente, sin dibujarlo realmente.
Nick Gammon

3

Un boceto de prueba para el Arduino Uno:

char buffer[10];

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

void loop() {
}

Como escribió @JRobert, el "habría" es la clave. Hasta donde sé, solo snprintf y vsnprintf devuelven un número "would have".

Creo que la razón es poder saber si la cadena se truncó. Suponga que el parámetro 'tamaño' es 25 y que la cadena de formato es muy larga, entonces el valor de retorno se puede probar contra 25. Si el valor de retorno fue 26 (el "tendría" número de bytes), entonces la cadena se truncó.
No fue posible recuperar esta información cuando el número "habría" no estaba disponible.


2

Para completar, la página del manual para fprintfestados:

La función snprintf () será equivalente a sprintf (), con la adición del argumento n que establece el tamaño del búfer al que se refiere s. Si n es cero, no se escribirá nada y s puede ser un puntero nulo. De lo contrario, los bytes de salida más allá del n-1 se descartarán en lugar de escribirse en la matriz, y se escribe un byte nulo al final de los bytes realmente escritos en la matriz.

y, más relevante:

Una vez completada con éxito, la función snprintf () devolverá el número de bytes en los que se escribirían si no hubiera sido lo suficientemente grande, excluyendo el byte nulo de terminación.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.