flotador - Cómo convertir o emitir un flotante en su secuencia de bits, como una larga
diferencia entre double y float java (5)
Asumo que estas flotantes son constantes y, por lo tanto, podrías escribir un pequeño programa para hacerlo como un ejercicio aislado: genera la salida según sea necesario. Desde ese pequeño programa, haga un trabajo cortante en el otro código.
Si tiene muchos de ellos, ¿por qué no simplemente escribir un script para crear el archivo apropiado para C.
Buen día, estoy trabajando en un entorno C de 16 bits y quiero convertir un valor flotante en su secuencia de bits, como un valor entero. Hay varias formas en que sé cómo lograr esto, una es con una unión; como:
union ConvertFloatToInt
{
float input;
unsigned long output;
};
esto "convertirá" los valores flotantes en un valor largo, leyendo la misma área de memoria, simplemente interpretándola de manera diferente.
union ConvertFloatToInt x;
x.input = 20.00;
resultado
x.output = 0x41A00000;
Otros métodos son lanzamientos de punteros vacíos ...
float input = 40.00;
unsigned long output;
void* ptr;
ptr = &input;
output = *(unsigned long*) ptr;
resultado
output = 0x42200000;
Esta es la idea de lo que estoy tratando de hacer, sin embargo, quiero que el compilador haga la conversión por mí, durante la compilación, no durante el tiempo de ejecución.
Necesito una para insertar los datos flotantes convertidos en una constante (const) unsigned de largo.
Estaba pensando en tratar de convertir el valor del flotador en un vacío, y luego el vacío en el largo sin signo. Algo como esto: (y sí, esto es incorrecto, no puedes lanzar al vacío)
const unsigned long FloatValue = (unsigned long) ((void) ((float) 20.654));
Hay alguna manera de hacer esto? Estaba pensando en algo con punteros vacíos, pero todos los punteros vacíos que conozco necesitan una variable, y las variables no se pueden usar en la asignación de valores const.
Editar
Estoy usando un compilador C90. La pregunta está prevista en el alcance del archivo.
Conclusión
La conclusión fue que no hay una solución real a esta pregunta, excepto cuando se trabaja en el alcance del bloque. Para el cual se dieron múltiples respuestas, y les agradezco a todos ustedes.
Mi solución
Esta no es una buena solución, sin embargo, resuelve mi problema, pero no creo que esto ayude a muchas personas tampoco. Creé un pequeño programa para un propósito de demostración. Este no es el código de mi proyecto, y tampoco el compilador utilizado en mi proyecto (antes de que alguien diga que no es un compilador C90)
El compilador utilizado en la demostración: gcc (Ubuntu / Linaro 4.6.3-1ubuntu5) 4.6.3
typedef union
{
float myfloat;
unsigned long mylong;
} custom_type;
typedef struct
{
int a;
int b;
custom_type typeA;
custom_type typeB;
} my_struct;
const my_struct myobj =
{
1,2,3.84F,4
};
int main(void)
{
printf(":: %f/n", myobj.typeA.myfloat);
printf(":: %ul/n", myobj.typeA.mylong);
return 0;
}
Salida
:: 3.840000
:: 1081459343l
Esto es un poco crudo, sin embargo, funciona en el alcance del archivo (pero genera advertencias).
Deberías saber algo sobre los estándares de coma flotante de IEEE. http://en.wikipedia.org/wiki/IEEE_floating-point_standard
obtener las fracciones de bits y obtener los bits de exponente y procesarlos en un largo
Puede lograr su propósito definiendo una constante de flotación y luego una macro:
const float _FloatValue = 20.654;
#define FloatValueL *((unsigned long *) &_FloatValue)
Puede usar un literal compuesto C99:
const unsigned long FloatValue =
*(unsigned long *) &(float) {20.654f};
Tenga en cuenta que el inicializador no es una expresión constante, por lo que FloatValue
solo se puede declarar en el ámbito del bloque y no en el ámbito del archivo.
Puedes hacer esto escribiendo a mano a través de una unión anónima:
unsigned int i = ((union { float f; unsigned int i; }){5.0}).i;
Tenga en cuenta que este inicializador no es una expresión constante y, por lo tanto, no se puede usar en el alcance del archivo.
El tipo de juego a través de una unión se especifica para ser permitido por el estándar en una nota al pie:
c11
6.5.2.3 Estructura y miembros del sindicato
95) Si el miembro utilizado para leer el contenido de un objeto de unión no es el mismo que el miembro utilizado por última vez para almacenar un valor en el objeto, la parte apropiada de la representación de objeto del valor se reinterpreta como una representación de objeto en el nuevo escriba como se describe en 6.2.6 (un proceso a veces llamado '''' tipo de juego de palabras ''''). Esto podría ser una representación de trampa.
Desde un punto de vista práctico, aunque no puede usar este método para inicializar una constante de alcance de archivo, podría escribir una función de inicialización que cargue los valores en variables de alcance de archivo durante el tiempo de inicialización del programa o módulo.
No va a encontrar un método portátil que le permita calcular los valores como una expresión constante en tiempo de compilación, porque las representaciones de objetos cubiertas por la sección 6.2.6 de la norma solo se aplican en tiempo de ejecución. De lo contrario, se requeriría un compilador cruzado para simular y no solo parametrizar el entorno de ejecución de su objetivo.
Anexo: este es C ++ válido, con la condición de que el tipo de union
debe ser nombrado:
union u { float f; unsigned int i; };
unsigned int i = u{5.0}.i;
Entonces, si está dispuesto a escribir en C / C ++ híbrido y compilar con un compilador de C ++, entonces puede realizar el reparto en tiempo de compilación.