sin ninguna información adicional acerca de lo que su código está haciendo, yo recomendaría el diseño de todas sus interfaces como este:
size_t foobar(char *dest, size_t buf_size, /* operands here */)
con la semántica como snprintf
:
dest
puntos a un buffer de tamaño al menos buf_size
.
- Si
buf_size
es cero, los punteros nulos/no válidos son aceptables para dest
y no se escribirá nada.
- Si
buf_size
es distinto de cero, dest
es siempre nulo-terminado.
- Cada función
foobar
devuelve la longitud de la salida completa no truncada; la salida se ha truncado si buf_size
es menor o igual que el valor de retorno.
De esta forma, cuando la persona que llama puede conocer fácilmente el tamaño del búfer de destino que se requiere, se puede obtener un búfer lo suficientemente grande por adelantado. Si la persona que llama no puede saber fácilmente, puede llamar a la función una vez con un argumento cero para buf_size
, o con un búfer que sea "probablemente lo suficientemente grande" y solo vuelva a intentarlo si se quedó sin espacio.
También puede hacer una versión envolvente de esas llamadas análoga a la función GNU asprintf
, pero si desea que su código sea lo más flexible posible, evitaría hacer cualquier asignación en las funciones de cadena reales. Manejar la posibilidad de falla siempre es más fácil a nivel del llamador, y muchos llamantes pueden asegurarse de que la falla nunca sea posible usando un búfer local o un búfer que se obtuvo mucho antes en el programa para que el éxito o el fracaso de una operación mayor es atómico (lo que simplifica enormemente el manejo de errores).
¿Usar C en primer lugar cuenta como un gotcha? '/ * ouch, ¡para! ¡es una broma! */' – delnan
¿Desea utilizar' char * 'o caracteres anchos? – anatolyg
@anatolyg: ¿Por qué alguien querría usar caracteres anchos? Uhg. –