如何将float转换或转换为其位序列,例如long

时间:2012-08-03 13:07:52

标签: c casting floating-point

美好的一天, 我在16位C环境中工作,我想将浮点值转换为其位序列,如整数值。 我知道如何实现这一目标有多种方式,一种是联盟;如:

union ConvertFloatToInt
{  
   float input;  
   unsigned long  output;  
};

这会将浮动值“转换”为长值,方法是读取相同的内存区域,只是以不同的方式解释它。

union ConvertFloatToInt x;
x.input = 20.00;

结果

x.output = 0x41A00000;

其他方法是void指针强制转换......

float input = 40.00;
unsigned long output;
void* ptr;
ptr = &input;
output = *(unsigned long*) ptr;

结果

output = 0x42200000;

这是我想要做的事情的想法,但是,我希望编译器在构建期间为我做转换,而不是在运行时。

我需要将转换后的浮动数据插入常量(const)unsigned long。

我正在考虑尝试将浮点值转换为void,然后将void转换为unsigned long。 这样的事情:(是的,这是不正确的,你不能投入虚空)

const unsigned long FloatValue = (unsigned long) ((void) ((float) 20.654));

有没有办法做到这一点?我想的可能是void指针,但我知道的所有void指针都需要一个变量,并且变量可能不会用于const值的赋值。

修改

我正在使用C90编译器。 问题出在文件范围内。

结论

结论是除了在块范围内工作外,没有真正的解决方案。给出了多个答案,我感谢你们所有人。

我的解决方案

这不是一个好的解决方案,但它解决了我的问题,但我不认为这对许多人也有帮助。 我创建了一个用于演示目的的小程序。这不是我的项目代码,也不是我的项目中使用的编译器(在有人说这不是C90编译器之前)

演示中使用的编译器: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;
}

输出

:: 3.840000
:: 1081459343l

这有点粗糙,但它适用于文件范围(但会生成警告)。

5 个答案:

答案 0 :(得分:5)

你可以通过匿名联盟打字:

unsigned int i = ((union { float f; unsigned int i; }){5.0}).i;

请注意,此初始化程序不是常量表达式,因此不能在文件范围内使用。

脚注中的标准允许通过联合进行类型标记:

  

     

6.5.2.3结构和工会成员

     

95)如果用于读取union对象内容的成员与上次使用的成员不同   在对象中存储一个值,该值的对象表示的相应部分被重新解释   作为6.2.6中描述的新类型中的对象表示(有时称为''类型的过程)   双关语””)。这可能是陷阱表示。

从实际角度来看,虽然您不能使用此方法初始化文件范围常量,但您可以编写初始化函数,在程序或模块初始化时将值加载到文件范围变量中。

您不会找到允许您将值计算为编译时常量表达式的可移植方法,因为标准6.2.6节所涵盖的对象表示仅适用于运行时。否则,交叉编译器将需要模拟,而不仅仅是参数化其目标的执行环境。


附录:此有效的C ++,条件是union类型必须命名:

union u { float f; unsigned int i; };
unsigned int i = u{5.0}.i;

因此,如果您愿意使用混合C / C ++编写并使用C ++编译器进行编译,那么您可以在编译时执行转换。

答案 1 :(得分:1)

您可以使用C99复合文字:

const unsigned long FloatValue =
        *(unsigned long *) &(float) {20.654f};

请注意,初始值设定项不是常量表达式,因此FloatValue只能在块范围内声明,而不能在文件范围内声明。

答案 2 :(得分:1)

我假设这些浮点数是常量,因此你可以编写一个小程序作为一次性练习 - 根据需要生成输出。从那个小程序做一个cut'n'paste工作到其他代码。

如果你有很多,为什么不写一个脚本来为C创建适当的文件。

答案 3 :(得分:0)

您应该了解有关IEEE浮点标准的一些事情。 http://en.wikipedia.org/wiki/IEEE_floating-point_standard

获取分数位并获得指数位并将它们处理为长

答案 4 :(得分:0)

您可以通过定义浮点常量然后定义宏来实现您的目的:

const float _FloatValue = 20.654;
#define FloatValueL *((unsigned long *) &_FloatValue)