Especificadores de formato incorrecto en scanf (o) printf

A partir de la función printf , entiendo lo siguiente a partir de algunas referencias y experimentos.

  • Cuando intentamos imprimir un valor entero con especificadores de formato que se usan para flotar (o) doble y viceversa, el comportamiento es impredecible .
  • Pero es posible usar %c para imprimir el equivalente de caracteres del valor entero. También es aceptable el uso de %d para imprimir el valor ASCII (representaciones enteras) del carácter.

Del mismo modo, ¿cuál es el comportamiento de scanf , si hay una falta de coincidencia de especificador de formato y los argumentos pasados ​​a scanf . ¿Los estándares lo definen?

Los argumentos variables (los que coinciden con las elipsis, ... ) se promocionan por defecto . Eso significa que todos los tipos integrales más cortos se promocionan a int (o unsigned, según corresponda). No hay diferencia entre enteros y personajes ( creo ). La diferencia entre %d y %c en printf es simplemente la forma en que se formatea el valor.

scanf es una olla de pescado diferente. Todos los argumentos que pasa son punteros . No hay promoción predeterminada entre punteros, y es crucial que pase el especificador de formato exacto que coincida con el tipo de punta.

En cualquier caso, si el especificador de formato no coincide con el argumento proporcionado (por ejemplo, pasar un int * a un %p en printf ), el resultado es un comportamiento indefinido , que es mucho peor que ser “impredecible”, es decir, su progtwig simplemente está mal formado.

En primer lugar, debido a la promoción, el tipo correspondiente a una especificación de conversión podría no ser el mismo que el tipo que se pasa a la función. Por ejemplo, los caracteres se promueven en ints, por lo que printf (“% c”) realmente esperan un int, que luego se convierte en un carácter sin signo. Pasar un int directamente tiene el mismo efecto que pasar ese int arrojado a un char sin signo, y por lo tanto es seguro.

Si el argumento no tiene el tipo esperado, por ejemplo, si pasa un flotante en lugar de un entero, el resultado no está definido.

Es particularmente catastrófico con scanf (), porque los argumentos son punteros. Si pasa, digamos un puntero a un char cuando la función espera un puntero a un flotador, entonces la función intentará escribir (decir) 4 bytes en una ubicación de 1 byte, lo cual es malo. Es muy posible que obtengas un segfault.