首先,让我解释一下环境。我将C用于嵌入式32位微控制器。通过各种工具进行单元测试,但结果相同。 printf仅用于MinGW的测试。
我正在尝试将数据从float32数组(4字节数组)(IEEE754)复制到字节数组中。
我仅在这里使用十六进制数据,重要的是十六进制值的位置准确,即:
If CalibData[0] = 01 02 03 04
然后数据应该看起来像这样:
Data[0] = 01
Data[1] = 02
Data[2] = 03
Data[3] = 04
我能想到的可能性类似于下面提到的代码块:
/*CalibData is a Global variable and change by other components, I am only reading it here*/
float32 CalibData [1920];
/*Data is an argument for my function and shall return it with values read from CalibData*/
int Data[7680];
/* Approach 1: */
uint16_t dataElementCounter = 0;
for (uint16_t i = 0; i < 1920; i++)
{
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 24);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 16);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 8);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32)calib_Data[i]);
dataElementCounter++;
}
/* Approach 2: */
for (uint16_t i = 0; i < 1920; i++)
{
memcpy((uint8*) Data[0], &calib_Data[i],sizeof(float));
}
现在的问题是,如果我正在使用方法1,那么很难在没有硬件的情况下测试数据是否已正确复制,因为通过单元测试或printf对其进行测试始终会提供截断的数据。例如
if CalibData[0] = 1.0;
根据IEEE754,十六进制应为0x3F 0x80 0x00 0x00,但在单元测试或printf中,它将像这样:
CalibData >> 24是分数1.0 /16777216。当转换为uint32时,它将截断为0。CalibData >> 16是分数1.0 /65536。同样。CalibData >> 8是分数1.0 /256。同样。CalibData为1.0。作为uint32,它将变为1。
所以数据将显示为:
Data[0] = 0
Data[1] = 0
Data[2] = 0
Data[3] = 1
如果我使用的是方法2,则代码将在Data中显示垃圾值。
请告诉我一种更好的方法或改进上述方法之一。
问候
由于将(uint32)
转换为float
而导致的错误uint32
,这不是您想要的。
您最好的选择是此摘录:
union {
float f;
uint8 b[4];
} u;
u.f = calib_Data[i];
Data[dataElementCounter] = u.b[0];
dataElementCounter++;
Data[dataElementCounter] = u.b[1];
dataElementCounter++;
Data[dataElementCounter] = u.b[2];
dataElementCounter++;
Data[dataElementCounter] = u.b[3];
dataElementCounter++;
请注意,这不符合C标准。但是它可能会在您的实际系统上运行。
编辑1
仍然不符合要求,但不使用union
,可以使用强制转换的指针来模拟:
const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
Data[dataElementCounter] = b[0];
dataElementCounter++;
Data[dataElementCounter] = b[1];
dataElementCounter++;
Data[dataElementCounter] = b[2];
dataElementCounter++;
Data[dataElementCounter] = b[3];
dataElementCounter++;
这类似于codetest的答案,甚至更好地建议使用memcpy()
:
memcpy(Data + dataElementCounter, calib_Data + i, sizeof calib_Data[i]);
dataElementCounter += sizeof calib_Data[i];
最后一个选项有两个主要优点:
calib_Data
的数据类型的大小。编辑2
要求:您必须交换字节。
如果目标系统是固定的,并且如果您完全确定自己在做什么,那么要做的第一件事就是在注释中记录下来。此外,您可能想检查编译器:
#if !defined(MY_COMPILER_ID)
#error Compiler not supported
#endif
要以相反的顺序存储浮点数,可以使用带有反向索引的EDIT 1的第一种选择:
const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
Data[dataElementCounter] = b[3];
dataElementCounter++;
Data[dataElementCounter] = b[2];
dataElementCounter++;
Data[dataElementCounter] = b[1];
dataElementCounter++;
Data[dataElementCounter] = b[0];
dataElementCounter++;
[为了使其在将来免受calib_Data
数据类型大小的更改的影响,您需要一个循环:
const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
int b_i;
for (b_i = sizeof calib_Data[i] - 1; b_i >= 0; --b_i) {
Data[dataElementCounter] = b[b_i];
dataElementCounter++;
}