varias sprintf snprintf serial print multiple leer imprimir ejemplo caracteres cadena c printf

c - snprintf - sprintf arduino ejemplo



¿Pueden las cadenas de entrada y salida a sprintf() ser iguales? (2)

He usado este tipo de convenciones muchas veces en mi código en el pasado:

strcpy ( cTmpA, "hello" ); sprintf ( cTmpA, "%s world", cTmpA );

Recientemente cambié mi compilador de C heredado a Visual Studio 2005 y descubrí que obtuve una cadena distorsionada como resultado del código anterior. Entonces se me ocurrió que tal vez el comportamiento de sprintf () no está definido rígidamente donde una de las entradas coincide con la cadena de salida.

¿Es válido el código anterior K&R C? Si no es así, ¿cómo puedo encontrar todos los lugares en mi código donde ocurrió este tipo de llamada a sprintf ()?


La mayoría de las implementaciones de sprintf() no copian la cadena de formato y en su lugar usan un puntero dentro de la cadena que pasaste. Si el formato y la salida apuntan a la misma memoria, se producirán resultados impares.

Y realmente deberías usar snprintf() que te protege contra desbordamientos de búfer.

Para encontrar todas las llamadas, ponga #define sprintf +++ en un encabezado común, busque y vuelva a compilar todas las fuentes. Eso debería darle una lista de errores junto con el nombre del archivo y los números de línea :) O use la búsqueda recursiva en su lugar de IDE.

Si desea recortar esta lista a las que usa el mismo puntero para ambos argumentos, use esta macro:

#define sprintf(output,format,...) check_sprintf(__FILE__,__LINE__,output,format,....)

Tenga en cuenta que no todos los compiladores admiten macros con varargs. Luego define una nueva función check_sprintf :

int check_sprintf (char*filename,int line,char*output,char*format,...) { va_list args; int len; if(output==format) { fprintf(stderr, "Output and format are the same at %s:%d", filename, line); abort(); } va_start (args, format); len = vsprintf (output, format, args); va_end (args); return len; }

[EDITAR] Acabo de ver que estás hablando sobre el resultado y el primer argumento. Puede reutilizar el código de arriba y llamar a va_arg() para obtener el primer argumento y usarlo en la comparación.


Si bien es válido para K&R C, es probable que desee saber más bien si es POSIX válido; consulte la especificación de sprintf . Leemos:

Si la copia se realiza entre objetos que se superponen como resultado de una llamada a sprintf () o snprintf (), los resultados no están definidos.