La venerable función snprintf() ...
int snprintf( char *restrict buffer, size_t bufsz, const char *restrict format, ... ); ¿Cómo tiene sentido que el tamaño del búfer sea size_t , pero que el tipo de retorno sea solo un int ?
Si se supone que snprintf() puede imprimir más de INT_MAX caracteres en el búfer, seguramente debe devolver un ssize_t o un size_t con (size_t) - 1 indicando un error, ¿verdad?
Y si se supone que no puede imprimir más de INT_MAX caracteres, ¿por qué bufsz es un size_t en lugar de, por ejemplo, un unsigned o un int ? O, ¿está al menos oficialmente obligado a mantener valores no mayores que INT_MAX ?
printf es anterior a la existencia de size_t y tipos "portátiles" similares; cuando printf se estandarizó por primera vez, el resultado de sizeof era un int .
Esta es también la razón por la cual el argumento en la lista de argumentos de printf leído para un * ancho o precisión en el formato es un int en lugar de un size_t .
snprintf es más reciente, por lo que el tamaño que toma como argumento se definió como size_t , pero el valor de retorno se mantuvo como un int para que sea igual que printf y sprintf .
Tenga en cuenta que puede imprimir más de INT_MAX caracteres con estas funciones, pero si lo hace, el valor devuelto no se especifica. En la mayoría de las plataformas, un int y un size_t se devolverán de la misma manera (en el registro de valor de retorno principal), solo que un valor de size_t puede estar fuera del rango de un int . Tantas plataformas realmente devuelven un size_t (o ssize_t ) de todas estas rutinas y las cosas que están fuera de rango generalmente funcionarán bien, aunque el estándar no lo requiera.
La discrepancia entre el tamaño y el rendimiento se ha discutido en el grupo de estándares en el hilo https://www.austingroupbugs.net/view.php?id=761 . Aquí está la conclusión publicada al final de ese hilo:
Investigaciones posteriores han demostrado que el comportamiento cuando el valor de retorno se desbordaría int fue aclarado por WG14 en C99 al agregarlo a la lista de comportamientos indefinidos en el Anexo J. Se actualizó en C11 con el siguiente texto:
"J.2 Comportamiento indefinido El comportamiento es indefinido en las siguientes circunstancias: [saltar]: el número de caracteres o caracteres anchos transmitidos por una función de salida formateada (o escritos en una matriz, o que se habrían escrito en una matriz) es mayor que INT_MAX (7.21.6.1, 7.29.2.1)."
Tenga en cuenta que esta descripción no menciona el argumento de tamaño de snprintf o el tamaño del búfer.
Si se supone que
snprintf()puede imprimir más deINT_MAXcaracteres en el búfer, seguramente debe devolver unssize_to unsize_tcon(size_t) - 1indicando un error, ¿verdad?
No exactamente.
C también tiene un límite ambiental para fprintf() y amigos.
El número de caracteres que se puede producir mediante una única conversión será de al menos 4095". C17dr § 7.21.6.1 15
Cualquier valor superior a 4095 por % pone en riesgo la portabilidad y, por lo tanto, incluso a 16 bits ( int INT_MAX = 32767 ), es suficiente para la mayoría de los propósitos de código portátil.
Nota: ssize_t no forma parte de la especificación C.