2010-05-31 43 views
16

理想情况下,下面的代码将采取IEEE 754表示一个浮子,并将其转换为十六进制转换IEEE 754浮点数与C诅咒 - printf的

void convert() //gets the float input from user and turns it into hexadecimal 
{ 
    float f; 
    printf("Enter float: "); 
    scanf("%f", &f); 
    printf("hex is %x", f); 
} 

我也不太清楚什么错。它将数字转换为十六进制数字,但却是非常错误的数字。

123.1443 gives 40000000 
43.3  gives 60000000 
8  gives 0 

所以它正在做一些事情,我只是不太确定是什么。

当你传递一个float作为参数传递给一个可变参数函数(如printf()),它提升为double,这是两倍大的帮助,将不胜感激

+0

''float'在各种函数中被提升为'double'(请参阅James McNellis的回答)。尝试'printf(“十六进制是%lx”,f);'而是。对于可移植代码,请查看sizeof(double)与sizeof(int)和sizeof(long)的比较,以确定是使用“x”还是“lx”。 – tomlogic 2010-06-01 15:17:24

+0

你怎么知道它是IEEE 754? – 2015-06-04 14:08:01

+0

@tomlogic:对于可移植代码,不要将浮点值传递给'printf',其格式需要一个整数。即使尺寸恰好匹配,行为也是未定义的。 (来自7年的问候,不要问) – 2017-07-28 17:31:49

回答

24

float(至少在大多数平台)。要解决这个问题

一种方式是通过当它作为参数传递给printf()float强制转换为unsigned int

printf("hex is %x", *(unsigned int*)&f); 

这也是比较正确的,因为printf()使用的格式说明,以确定如何每个参数都很大。

从技术上讲,该解决方案违反了strict aliasing rule

unsigned int ui; 
memcpy(&ui, &f, sizeof (ui)); 

printf("hex is %x", ui); 

这两种解决方案都是基于这样的假设sizeof(int) == sizeof(float),这是许多32位的情况:您可以通过复制float的字节到unsigned int,然后递过来printf()解决这个问题系统,但不一定是这种情况。

+1

为了避免违反严格的别名规则,试试*(volatile unsigned int *)(volatile float *)(&f); – Joshua 2010-05-31 02:44:42

+0

)为什么不能只是printf( “hex is%x \ n”,(unsigned int)f) 假设f可以适合unsigned int – Nyan 2010-05-31 12:38:42

+4

@Nyan:因为那不会将位重新解释为一个无符号的值,所以将float转换为一个无符号的值(因此,24.12会变成24,这不是理想的结果) – 2010-05-31 13:13:15

12

支持时,使用%a将浮点数转换为标准的十六进制格式。这里是唯一可以找到的document列出%a选项。

否则,您必须将浮点值的位拖入已知大小的整数类型中。如果你知道,例如,float和int中有32位,你可以做一个快速转换:

printf("%08X" , *(unsigned int*)&aFloat); 

如果要较少地依赖于尺寸,你可以使用一个联盟:

union { 
    float f; 
//char c[16]; // make this large enough for any floating point value 
    char c[sizeof(float)]; // Edit: changed to this 
} u; 

u.f = aFloat; 
for (i = 0 ; i < sizeof(float) ; ++i) printf("%02X" , u.c[i] & 0x00FF); 

循环的顺序取决于体系结构的字节顺序。这个例子是big endian。

无论哪种方式,浮点格式可能无法移植到其他体系结构。 %a选项的目的是。

+0

+1:我不熟悉'% ''格式说明符,现在我觉得很笨:-) – 2010-05-31 02:53:47

+0

+1了解%a。为什么'char [16]''而不是'char [sizeof(float)]''? – 2010-05-31 06:30:03

+0

C99是另一个提到它的文档:-) – 2015-06-04 14:10:19

1

这个怎么样:?

int main(void){ 
    float f = 28834.38282; 
    char *x = (char *)&f; 
    printf("%f = ", f); 

    for(i=0; i<sizeof(float); i++){ 
    printf("%02X ", *x++ & 0x0000FF); 
    } 

    printf("\n"); 
} 
3

HEX为浮动

我花了相当长的时间试图找出如何将HEX输入从格式化为IEE754浮浮到串行连接转换。现在我懂了。只是想分享,以防它可以帮助别人。

#include <stdio.h> 
#include <stdlib.h> 
int main(int argc, char *argv[]) 
{ 

    uint16_t tab_reg[64]     //declare input value recieved from serial connection 
    union IntFloat { int32_t i; float f; }; //Declare combined datatype for HEX to FLOAT conversion 
    union IntFloat val;      
    int i; 
    char buff[50];       //Declare buffer for string 

    i=0; 

    //tab_reg[i]=0x508C;     //to test the code without a data stream, 
    //tab_reg[i+1]=0x4369;     //you may uncomment these two lines. 


    printf("Raw1: %X\n",tab_reg[i]);  //Print raw input values for debug 
    printf("Raw2: %X\n",tab_reg[i+1]);  //Print raw input values for debug 

    rs = sprintf(buff,"0X%X%X", tab_reg[i+1], tab_reg[i]); //I need to swap the words, as the response is with the opposite endianness. 
    printf("HEX: %s",buff);     //Show the word-swapped string 
    val.i = atof(buff);      //Convert string to float :-) 
    printf("\nFloat: %f\n", val.f);   //show the value in float 

} 

输出:

Raw1: 508C 
Raw2: 436A 
HEX: 0X436A508C 
Float: 234.314636 
2

这种做法总是工作很细对我说:

union converter{ 
float f_val; 
unsigned int u_val; 
}; 

union converter a; 
a.f_val = 123.1443f; 
printf("my hex value %x \n", a.u_val); 
2

愚蠢简单的例子:

unsigned char* floatToHex(float val){ 
    unsigned char* hexVals = malloc(sizeof(float)); 
    hexVals[0] = ((unsigned char*)&val)[0]; 
    hexVals[1] = ((unsigned char*)&val)[1]; 
    hexVals[2] = ((unsigned char*)&val)[2]; 
    hexVals[3] = ((unsigned char*)&val)[3]; 
    return hexVals; 
} 

很明显的解决方案时,我想它出。无需掩码,memcpy或其他必要的技巧。

在上面的例子中,它是为了一个特定的目的,我知道浮点数是32位。一个更好的解决方案,如果您不确定系统:

unsigned char* floatToHex(float val){ 
    unsigned char* hexVals = malloc(sizeof(float)); 
    for(int i = 0; i < sizeof(float); i++){ 
     hexVals[i] = ((unsigned char*)&val)[i]; 
    } 
    return hexVals; 
} 
0

什么终于为我工作(令人费解,因为它似乎):

#include <stdio.h> 
int main((int argc, char** argv) 
{ 
    float flt = 1234.56789; 
    FILE *fout; 
    fout = fopen("outFileName.txt","w"); 
    fprintf(fout, "%08x\n", *((unsigned long *)&flt); 
     /* or */ 
    printf("%08x\n", *((unsigned long *)&flt); 
}