如何将float转换或转换为其位序列,如long [英] How to convert or cast a float into its bit sequence such as a long

查看:201
本文介绍了如何将float转换或转换为其位序列,如long的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Good day,
我在一个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。



我想要将float值转换为void,然后将void转换为unsigned long。
这样的东西:(和这是不正确的,你不能强制转换为void)

  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 \\\
,myobj.typeA.myfloat);
printf(::%ul\\\
,myobj.typeA.mylong);
return 0;
}

输出

  :: 3.840000 
:: 1081459343l

解决方案

你可以通过类型冲击来做到这一点通过匿名联合:

  unsigned int i =((union {float f; unsigned int i;}){5.0} 。一世; 

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



通过联合体的打字通过标准在脚注中指定:


c11 的问题



6.5.2.3结构和联合成员



95)如果用于读取union对象的内容的成员与成员不同最后用于
在对象中存储一个值,该值的对象表示的适当部分被重新解释为
作为新类型中的对象表示,如第6.2.6节所述(一个过程有时称为 'type
punning'')。这可能是一个陷阱表示。


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



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






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

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

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


Good day, I am working in a 16-bit C environment, and I want to convert a float value into its bit sequence such as an integer value. There are multiple ways I know how to achieve this, one is with a union; such as:

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

this will "convert" the floating values into a long value, by reading the same memory area, just interpreting it differently.

union ConvertFloatToInt x;
x.input = 20.00;

result

x.output = 0x41A00000;

Other methods are void pointer casts...

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

result

output = 0x42200000;

This is the idea of what I am trying to do, however, I want the compiler to do the conversion for me, during build, not during run time.

I need a to insert the converted floating data into a constant (const) unsigned long.

I was thinking of trying to convert the float value into a void, and then the void into the unsigned long. Something like this: (and yes this is incorrect, you can not cast to a void)

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

Is there some way to do this? I was thinking maybe something with void pointers, but all void pointers I know of needs a variable, and variables may not be used in the assignment of const values.

Edit

I am using a C90 compiler. The question is intended in the file scope.

Conclusion

The conclusion was that there is no real solution to this question except when working in the block scope. For which multiple answers were given, and I thank all of you.

My Solution

This is not a good solution, however it solves my problem, but I do not think that this will help many people either. I created a small program for a demonstration purpose. This is not my projects code, and also not the compiler used in my project (before someone says that this is not a C90 compiler)

The compiler used in the demonstration: 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;
}

Output

:: 3.840000
:: 1081459343l

This is little bit crude, however it works in the file scope (but generates warnings).

解决方案

You can do this by type-punning through an anonymous union:

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

Note that this initialiser is not a constant expression and so cannot be used at file scope.

Type-punning through a union is specified to be allowed by the standard in a footnote:

6.5.2.3 Structure and union members

95) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

From a practical point of view, although you cannot use this method to initialise a file-scope constant, you could write an initialisation function that loads the values into file-scope variables at program or module initialisation time.

You're not going to find a portable method that allows you to calculate the values as a compile-time constant expression, because the object representations covered by section 6.2.6 of the standard only apply at run time. Otherwise, a cross-compiler would be required to simulate and not just parametrise the execution environment of its target.


Addendum: this is valid C++, with the condition that the union type must be named:

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

So if you're willing to write in hybrid C/C++ and compile with a C++ compiler, then you can perform the cast at compile time.

这篇关于如何将float转换或转换为其位序列,如long的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆