¿Cuál es el comportamiento de printf al imprimir un int como flotante?

4 minutos de lectura

¿Cual es el comportamiento de printf al imprimir un int
ada

Estoy usando dev cpp en windows7 para compilar mi código.

int d = 0x12;
char* e = (char*)&d;
printf("%d %d\n", sizeof (int), sizeof (float));
printf("%p %p\n", &d, (float*)&d);
printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]);
printf(" %d | %x | %#1x | %#1x | %#1x |%p\n", d,  e[0], e[1], e[2], e[3], &e[0]);
getchar();

4 4 
0028FF40 0028FF40
0028FF40 0028FF40 0028FF41 0028FF42 0028FF43  
18 | 12 | 0 | 0 | 0 |0028FF40

Puede ver que si uso %d para imprimir d, está imprimiendo los 4 bytes de e bien. Pero si uso %f como a continuación, muestra ceros en el lugar donde se debe imprimir el primer byte de e. ¿Alguien puede ayudar con por qué sucede esto? ¿Por qué el contenido de e debería depender de cómo esté formateado d?

int d = 0x12;
char* e = (char*)&d;
printf("%d %d\n", sizeof (int), sizeof (float));
printf("%p %p\n", &d, (float*)&d);
printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]);
printf(" %f | %x | %#1x | %#1x | %#1x |%p\n", d,  e[0], e[1], e[2], e[3], &e[0]);
getchar();

La salida es:

4 4
0028FF40 0028FF40
0028FF40 0028FF40 0028FF41 0028FF42 0028FF43
 0.000000 | 0 | 0 | 0 | 0x28ff40 |76869F1D

  • Debe dejar de usar Dev-Cpp. Está extremadamente desactualizado y usa una versión antigua de GCC.

    – ThiefMaster

    20 de noviembre de 2011 a las 18:50

  • ¿Por qué estás lanzando? (int*) para (float*)? La programación ya es bastante difícil sin cosas como esta.

    –David Heffernan

    20 de noviembre de 2011 a las 19:30

  • Posible duplicado de ¿Qué puede pasar si se llama a printf con una cadena de formato incorrecta?

    – phuclv

    6 de mayo de 2017 a las 9:37

¿Cual es el comportamiento de printf al imprimir un int
Oliver Charlesworth

Comportamiento indefinido.

En la práctica, lo que está viendo probablemente se deba al hecho de que %f hace printf tirar de un double de su lista de argumentos, que es de 8 bytes*. Pero d tiene solo 4 bytes de tamaño, por lo que ahora todo está desalineado.

Recuérdalo printf es una función variádica, lo que significa que no tiene ningún tipo de seguridad; printf tiene que extraer bytes sin formato de la pila sin ayuda del compilador. Depende totalmente de usted asegurarse de que los argumentos se correspondan con precisión con la cadena de formato.


* Probablemente.

  • Tomé su respuesta en el sentido de que los bytes de e todavía están allí, pero es solo que los lee desde el lugar equivocado. Podría verificar haciendo un printf fundido en la siguiente línea. printf(” %f | %x | %#1x | %#1x | %#1x |%p\n”, (flotante)d, e[0]mi[1]mi[2]mi[3]&e[0]); Esto realmente dio los resultados correctos. Gracias por la explicación.

    – ada

    20 noviembre 2011 a las 19:00


¿Cual es el comportamiento de printf al imprimir un int
jeff dege

Te estás haciendo tropezar con la promoción de tipo automático.

Parece que está asumiendo que, dado que sizeof(int) == sizeof(float), puede pasar d como float o int indistintamente. Pero la cuestión es que en C no puedes pasar un flotador.

En C, cuando usa un char o un short en una expresión, se convierte automáticamente en un int. De manera similar, cuando usa un flotante en una expresión, se convierte automáticamente en un doble.

Entonces, cuando haces un printf(“%f”, d), el compilador inserta un int, es decir, cuatro bytes, en la pila, antes de realizar la llamada a la función. Luego, en la función, printf() ve “%f” y extrae ocho bytes de la pila. Cuatro bytes de los cuales son su “d”, y los otros cuatro son lo que sea que esté allí. En tu ejemplo, e[0] y mi[1].

Si desea imprimir “d” como un flotante, debe convertirlo explícitamente o asignarlo a una variable flotante. En cualquier caso, el compilador lo convertirá en un doble antes de llamar a printf(). (Nota: por extraño que parezca, “%f” se usa para imprimir dobles, no flotantes. No puede imprimir flotantes. Puede leer flotantes o dobles, con “%f” y “%lf”, en scanf(), pero en printf(), “%f” imprime dobles).

  • “cuando usa un flotante en una expresión, se convierte automáticamente en un doble”. esto es falso Los flotantes no se convierten implícitamente a doble en todas las expresiones, a menos que otro operando en la expresión sea doble (Conversión aritmétrica habitual). Lo que buscas se llama promociones de argumento predeterminadoque suceden solamente cuando A) float se pasa a la función sin prototipo, o B) float se pasa a la función que toma argumentos variables (el prototipo termina con , ...).

    – usuario694733

    26 de enero de 2016 a las 8:11


Sí, está extrayendo 8 bytes de la pila, cuatro de los cuales son 0x00000012, el resto depende del compilador (tal vez la dirección de retorno que se colocó en la pila cuando se construyó el marco de pila para printf).

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad