将 4 个整数的结构转换为浮点数
Converting a struct of 4 integers to a float
我是编程新手,指针和类型转换不强,所以需要一些帮助。
我正在使用 IAR Workbench 和 STM32L475。
从 Eeprom 加载它们后,我试图将结构中的 4 个字节转换为浮点数。
我知道 Big/Little Endian 和代码到其他 micro 的可移植性可能存在挑战,但请不要将此线程与此混为一谈,因为这对我来说现在并不重要。
我做错了什么,谢谢你的帮助?
请简单说明"for dummies"。
我收到 pe513 错误。
我的代码:
struct Test {
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
} TestStruct;
float x = 0.0;
uint8_t *TestStruct_ptr;
int main(void)
{
/* USER CODE BEGIN 1 */
TestStruct.Byte1 = 0x41; //float value = 23.10
TestStruct.Byte2 = 0xB8;
TestStruct.Byte3 = 0xCC;
TestStruct.Byte4 = 0xCD;
TestStruct_ptr = (float*)&TestStruct;
x = (float*) TestStruct_ptr;
// some code
return 0;
}
编辑:
我正在从 Eeprom 加载一个数组,并且必须 "collect" 一个包含四个 uint8 字节的数组到一个浮点数,它们在保存到 Eeprom 之前是结构的一部分。
明天上班时我会更新确切的错误消息。
我最终使用了 "union",因为这似乎是最好的解决方案。
我的示例代码现在如下所示:
union Eeprom {
struct {
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
};
float x;
uint8_t Array[4];
};
int main(void)
{
union Eeprom Test;
//assign values to individual bytes
Test.Byte1=0xCD;
Test.Byte2=0xCC;
Test.Byte3=0xB8;
Test.Byte4=0x41;
//Assign values as an array (here individual bytes, overwrites above assigned values).
//Data will be formatted as an array when loaded from E2prom.
Test.Array[0]=0xCD;
Test.Array[1]=0xCC;
Test.Array[2]=0xB8;
Test.Array[3]=0x41;
//Assign value as floating point value (overwrites the above assigned values)
Test.x = 23.1;
printf("FPvalue %3.2f \n Byte1 %x\n Byte2 %x\n Byte3 %x\n Byte4 %x\n
Array[0] %x\n Array[1] %x\n Array[2] %x\n Array[3] %x\n",
Test.x, Test.Byte1, Test.Byte2, Test.Byte3, Test.Byte4,
Test.Array[0], Test.Array[1], Test.Array[2], Test.Array[3]);
}
输出如下所示:
floatvalue 23.10
Byte1 cd
Byte2 cc
Byte3 b8
Byte4 41
Array[0] cd
Array[1] cc
Array[2] b8
Array[3] 41
您可以使用联合:
typedef union
{
struct
{
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
};
float floatvalue;
}TestT;
TestT Test;
Test.floatvalue = ...... //complete float
Test.Byte1 = ..... //single Byte to save in EEPROM
由于您不关心可移植性或字节顺序问题,您可以简单地复制字节 memcpy
:
memcpy(&x, &TestStruct, sizeof x);
您可能在某处看到过此选项或类似选项:
x = *(float*)&TestStruct; // BAD!!!!! dereferencing using wrong pointer type
不要这样做!它违反了严格的别名规则,即未定义的行为。
联合双关就可以了。
typedef union
{
uint32_t u32;
uint16_t u16[2];
uint8_t u8[4];
float f;
}b32data;
当您从 NV 内存中读取时,只需分配正确的成员而无需任何指针。
以这种方式输入双关语是违法的。正如其他人所提到的,联合可用于进行类型双关。或者,由于其意图似乎是要有一个字节可访问的浮点数,因此将 类型转换为 char
类型是合法的。因此,与其将变量的类型声明为 4 char
的结构,不如将其声明为 float
,然后输入双关语 unsigned char
并将其作为数组访问:
float x = 0.0;
unsigned char *test_ptr = (unsigned char *)&x;
int main(void)
{
/* USER CODE BEGIN 1 */
test_ptr[0] = 0x41; //float value = 23.10
test_ptr[1] = 0xB8;
test_ptr[2] = 0xCC;
test_ptr[3] = 0xCD;
// some code
return 0;
}
当然,字节的顺序将取决于端序。我保留了您的字节顺序,这对于大端目标应该是正确的。
我是编程新手,指针和类型转换不强,所以需要一些帮助。
我正在使用 IAR Workbench 和 STM32L475。 从 Eeprom 加载它们后,我试图将结构中的 4 个字节转换为浮点数。
我知道 Big/Little Endian 和代码到其他 micro 的可移植性可能存在挑战,但请不要将此线程与此混为一谈,因为这对我来说现在并不重要。
我做错了什么,谢谢你的帮助?
请简单说明"for dummies"。
我收到 pe513 错误。
我的代码:
struct Test {
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
} TestStruct;
float x = 0.0;
uint8_t *TestStruct_ptr;
int main(void)
{
/* USER CODE BEGIN 1 */
TestStruct.Byte1 = 0x41; //float value = 23.10
TestStruct.Byte2 = 0xB8;
TestStruct.Byte3 = 0xCC;
TestStruct.Byte4 = 0xCD;
TestStruct_ptr = (float*)&TestStruct;
x = (float*) TestStruct_ptr;
// some code
return 0;
}
编辑: 我正在从 Eeprom 加载一个数组,并且必须 "collect" 一个包含四个 uint8 字节的数组到一个浮点数,它们在保存到 Eeprom 之前是结构的一部分。 明天上班时我会更新确切的错误消息。
我最终使用了 "union",因为这似乎是最好的解决方案。
我的示例代码现在如下所示:
union Eeprom {
struct {
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
};
float x;
uint8_t Array[4];
};
int main(void)
{
union Eeprom Test;
//assign values to individual bytes
Test.Byte1=0xCD;
Test.Byte2=0xCC;
Test.Byte3=0xB8;
Test.Byte4=0x41;
//Assign values as an array (here individual bytes, overwrites above assigned values).
//Data will be formatted as an array when loaded from E2prom.
Test.Array[0]=0xCD;
Test.Array[1]=0xCC;
Test.Array[2]=0xB8;
Test.Array[3]=0x41;
//Assign value as floating point value (overwrites the above assigned values)
Test.x = 23.1;
printf("FPvalue %3.2f \n Byte1 %x\n Byte2 %x\n Byte3 %x\n Byte4 %x\n
Array[0] %x\n Array[1] %x\n Array[2] %x\n Array[3] %x\n",
Test.x, Test.Byte1, Test.Byte2, Test.Byte3, Test.Byte4,
Test.Array[0], Test.Array[1], Test.Array[2], Test.Array[3]);
}
输出如下所示:
floatvalue 23.10
Byte1 cd
Byte2 cc
Byte3 b8
Byte4 41
Array[0] cd
Array[1] cc
Array[2] b8
Array[3] 41
您可以使用联合:
typedef union
{
struct
{
uint8_t Byte1;
uint8_t Byte2;
uint8_t Byte3;
uint8_t Byte4;
};
float floatvalue;
}TestT;
TestT Test;
Test.floatvalue = ...... //complete float
Test.Byte1 = ..... //single Byte to save in EEPROM
由于您不关心可移植性或字节顺序问题,您可以简单地复制字节 memcpy
:
memcpy(&x, &TestStruct, sizeof x);
您可能在某处看到过此选项或类似选项:
x = *(float*)&TestStruct; // BAD!!!!! dereferencing using wrong pointer type
不要这样做!它违反了严格的别名规则,即未定义的行为。
联合双关就可以了。
typedef union
{
uint32_t u32;
uint16_t u16[2];
uint8_t u8[4];
float f;
}b32data;
当您从 NV 内存中读取时,只需分配正确的成员而无需任何指针。
以这种方式输入双关语是违法的。正如其他人所提到的,联合可用于进行类型双关。或者,由于其意图似乎是要有一个字节可访问的浮点数,因此将 类型转换为 char
类型是合法的。因此,与其将变量的类型声明为 4 char
的结构,不如将其声明为 float
,然后输入双关语 unsigned char
并将其作为数组访问:
float x = 0.0;
unsigned char *test_ptr = (unsigned char *)&x;
int main(void)
{
/* USER CODE BEGIN 1 */
test_ptr[0] = 0x41; //float value = 23.10
test_ptr[1] = 0xB8;
test_ptr[2] = 0xCC;
test_ptr[3] = 0xCD;
// some code
return 0;
}
当然,字节的顺序将取决于端序。我保留了您的字节顺序,这对于大端目标应该是正确的。