valor tipos tipo puede programacion pequeño para implícitamente implicitamente grande float demasiado datos dato convertir conversion como cast automatica c gcc type-conversion implicit-conversion

tipos - Comprender las conversiones implícitas para printf



no se puede convertir implícitamente el tipo double en float (2)

Los argumentos para va_arg funciones va_arg no se convierten, sintácticamente el compilador no sabe nada sobre los argumentos para tales funciones, por lo que no puede hacer eso. Sin embargo, los compiladores modernos sí saben interpretar la cadena de formato, por lo que pueden avisarte cuando algo sospechoso está sucediendo. Eso es lo que sucede cuando ves la advertencia de gcc.

Para ser más precisos, hay algunas promociones que se realizan para tipos enteros estrechos , se promueven a int y para float que se promociona a double . Pero eso es todo magia que puede suceder, aquí.

En resumen, use siempre el especificador de formato correcto.

Por cierto, para size_t partir de tu sizeof expresiones, la correcta es %zu .

El estándar C99 distingue entre conversiones de tipo implícito y explícito (6.3 conversiones). Supongo, pero no pude encontrar, que se realizan moldes implícitos, cuando el tipo de objetivo es de mayor precisión que la fuente, y puede representar su valor. [Eso es lo que considero que pasa de INT a DOBLE]. Dado eso, miro el siguiente ejemplo:

#include <stdio.h> // printf #include <limits.h> // for INT_MIN #include <stdint.h> // for endianess #define IS_BIG_ENDIAN (*(uint16_t *)"/0/xff" < 0x100) int main() { printf("sizeof(int): %lu/n", sizeof(int)); printf("sizeof(float): %lu/n", sizeof(float)); printf("sizeof(double): %lu/n", sizeof(double)); printf( IS_BIG_ENDIAN == 1 ? "Big" : "Little" ); printf( " Endian/n" ); int a = INT_MIN; printf("INT_MIN: %i/n", a); printf("INT_MIN as double (or float?): %e/n", a); }

Me sorprendió mucho encontrar ese resultado:

sizeof(int): 4 sizeof(float): 4 sizeof(double): 8 Little Endian INT_MIN: -2147483648 INT_MIN as double (or float?): 6.916919e-323

Entonces, el valor flotante impreso es un número de coma flotante subnormal cerca del muy mínimo doble positivo subnormal 4,9406564584124654 × 10 ^ -324. Cosas extrañas suceden cuando comento los dos printf por endianess, obtengo otro valor por el doble:

#include <stdio.h> // printf #include <limits.h> // for INT_MIN #include <stdint.h> // for endianess #define IS_BIG_ENDIAN (*(uint16_t *)"/0/xff" < 0x100) int main() { printf("sizeof(int): %lu/n", sizeof(int)); printf("sizeof(float): %lu/n", sizeof(float)); printf("sizeof(double): %lu/n", sizeof(double)); // printf( IS_BIG_ENDIAN == 1 ? "Big" : "Little" ); printf( " Endian/n" ); int a = INT_MIN; printf("INT_MIN: %i/n", a); printf("INT_MIN as double (or float?): %e/n", a); }

salida:

sizeof(int): 4 sizeof(float): 4 sizeof(double): 8 INT_MIN: -2147483648 INT_MIN as double (or float?): 4.940656e-324

  • gcc --version: (Ubuntu 4.8.2-19ubuntu1) 4.8.2
  • uname: x86_64 GNU / Linux
  • opciones del compilador donde: gcc -ox xc -Wall -Wextra-std = c99 --pedantic
  • Y sí, allí donde una advertencia:

x.c: In function ‘main’: x.c:15:3: warning: format ‘%e’ expects argument of type ‘double’, but argument 2 has type ‘int’ [-Wformat=] printf("INT_MIN as double (or float?): %e/n", a); ^

Pero todavía no puedo entender qué está pasando exactamente.

  • en little endianess considero MIN_INT como: 00 ... 0001 y MIN_DBL (Subnormal) como 100..00 #, comenzando con la mantisa, seguido por el exponente y concluyendo con el # como un bit de signo.
  • ¿Es esta forma de aplicar el especificador de formato "% e" en un int, es un elenco implícito ?, ¿una conversión reinterpretada?

Estoy perdido, por favor ilumíname.


printf("INT_MIN as double (or float?): %e/n", a);

La línea superior tiene un problema. No puedes usar %e para imprimir las entradas. El comportamiento no está definido.

Deberías usar

printf("INT_MIN as double (or float?): %e/n", (double)a);

o

double t = a; printf("INT_MIN as double (or float?): %e/n", t);

Publicación relacionada : esta publicación explica cómo usar los especificadores de impresión incorrectos en printf puede conducir a UB.