我有以下结构:
typedef union
{
struct
{
unsigned char ID;
unsigned short Vdd;
unsigned char B1State;
unsigned short B1FloatV;
unsigned short B1ChargeV;
unsigned short B1Current;
unsigned short B1TempC;
unsigned short B1StateTimer;
unsigned short B1DutyMod;
unsigned char B2State;
unsigned short B2FloatV;
unsigned short B2ChargeV;
unsigned short B2Current;
unsigned short B2TempC;
unsigned short B2StateTimer;
unsigned short B2DutyMod;
} bat_values;
unsigned char buf[64];
} BATTERY_CHARGE_STATUS;
我从数组中填充如下:
for(unsigned char ii = 0; ii < 64; ii++) usb_debug_data.buf[ii]=inBuffer[ii];
我可以看到该数组具有以下(任意)值:
inBuffer[0] = 80;
inBuffer[1] = 128;
inBuffer[2] = 12;
inBuffer[3] = 0;
inBuffer[4] = 23;
...
现在我希望通过更改QEditLine的文本来显示这些值:
str=QString::number((int)usb_debug_data.bat_values.ID);
ui->batID->setText(str);
str=QString::number((int)usb_debug_data.bat_values.Vdd)
ui->Vdd->setText(str);
str=QString::number((int)usb_debug_data.bat_values.B1State)
ui->B1State->setText(str);
...
但是,QEditLine文本值未按预期显示。我看到以下内容:
usb_debug_data.bat_values.ID = 80 (correct)
usb_debug_data.bat_values.Vdd = 12 (incorrect)
usb_debug_data.bat_values.B1State = 23 (incorrect)
似乎是'usb_debug_data.bat_values.Vdd',这是一个短片,没有从inBuffer [1]和inBuffer [2]中获取它的值。同样,'usb_debug_data.bat_values.B1State'应该从inBuffer [3]中获取它的值,但出于某种原因从inBuffer [4]中获取它的值。
知道为什么会这样吗?
答案 0 :(得分:3)
C和C ++可以自由地在结构的元素之间插入填充,并且在最后一个元素之外,无论出于何种目的(通常是效率,但有时因为底层架构根本不允许未对齐访问)。
所以你可能会发现两个字节长度的项目与两个字节的边界对齐,所以你最终会得到类似的东西:
unsigned char ID; // 1 byte
// 1 byte filler, aligns following short
unsigned short Vdd; // 2 bytes
unsigned char B1State; // 1 byte
// 3 bytes filler, aligns following int
unsigned int myVar; // 4 bytes
许多编译器将允许您具体说明如何打包结构,例如:
#pragma pack(1)
或gcc
:
__attribute__((packed))
属性。
如果您不想(或不能)打包您的结构,您可以恢复逐个字段的复制(可能是函数中最好的):
void copyData (BATTERY_CHARGE_STATUS *bsc, unsigned char *debugData) {
memcpy (&(bsc->ID), debugData, sizeof (bsc->ID));
debugData += sizeof (bsc->ID);
memcpy (&(bsc->Vdd), debugData, sizeof (bsc->Vdd));
debugData += sizeof (bsc->Vdd);
: : :
memcpy (&(bsc->B2DutyMod), debugData, sizeof (bsc->B2DutyMod));
debugData += sizeof (bsc->B2DutyMod); // Not really needed
}
你必须保持结构和功能的同步,这是一种痛苦,但希望它不会发生那么大的变化。
答案 1 :(得分:2)
默认情况下,结构不是压缩,因此编译器可以在成员之间插入填充。最常见的原因是确保一些机器相关的对齐。 wikipedia entry on data structure alignment是一个非常好的起点。你基本上有两个选择:
#pragma packed
或__attribute__((packed))__
。我通常更喜欢后者,因为它并没有让我的代码变得丑陋,而且在任何地方都没有特定的编译器特定装饰。
您可能会发现的下一件事是多字节整数的字节顺序也是特定于平台的。 Look up endianness for more details