问题描述
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} 。一世;
请注意,此初始化程序不是常量表达式,因此不能在文件范围使用。
通过联合体的打字通过标准在脚注中指定:
从实际的角度来看,虽然你不能使用这个方法来初始化文件范围常量,您可以编写一个初始化函数,在程序或模块初始化时将这些值加载到文件范围变量中。
你不会找到一个可移植的方法您可以将值计算为编译时常量表达式,因为标准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:
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!