Pascal 记录在记录中混合字和字节不能按预期工作

Jua*_*eto 1 delphi pascal record

我的数据是这样的(每两个'-'一个字节):

+----+--+----+----+
|0840|0C|00AD|0840|
+----+--+----+----+
Run Code Online (Sandbox Code Playgroud)

如果我使用此代码:错误

Type TAlarmasRATP = record
   Funcion   : word;
   Instancia : byte;
   Err_0     : word;
   Err_1     : word;
end;
Run Code Online (Sandbox Code Playgroud)

函数 = 4008,实例 = 0C,Err_0 = 08AD,Err_1 = 0040

如果我使用此代码:正确

Type TAlarmasRATP = record
   Funcion   : word;
   Instancia : byte;
   Err_0     : array [0..1] of byte;
   Err_1     : array [0..1] of byte;
end;
Run Code Online (Sandbox Code Playgroud)

函数 = 4008,实例 = 0C,Err_0 = AD00,Err_1 = 4008

为什么第一个不起作用?

Dal*_*kar 8

当使用记录类型时,字段根据规范对齐内部数据格式 - 记录类型

类型 以字节为单位对齐(32 位平台)
序数 类型的大小(即 1 for Byte、2 for Word、4 forCardinal或 8 for Int64
真实的 2 为Real48, 4 为Single, 8 为DoubleExtended
ShortString 1
Array 与数组的元素类型相同
Record 记录中字段的最大对齐
Set 类型的大小(1、2 或 4),否则始终为 1
所有其他 {$A}指令确定

这意味着:在第一个记录声明中,该Err_0字段将在Word边界上对齐,并且将在该Instancia字段后附加一个填充字节。

在第二个记录声明中,该Err_0字段将在Byte边界上对齐,因为它是一个 的数组,Byte并且该Instancia字段之后将没有填充。由于记录未打包,因此将在结构末尾插入一个填充字节 - 因此在两种情况下记录大小都将舍入为 8。

如果使用packed关键字,记录中的所有字段都将被打包到字节边界,并且记录的大小将恰好是字段大小的总和,末尾没有填充。

对于 7 的记录大小,您可以简单地声明:

type TAlarmasRATP = packed record
   Funcion   : Word;
   Instancia : Byte;
   Err_0     : Word;
   Err_1     : Word;
end;
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要 8 的大小,您应该通过定义另一个您从未使用过的字段在末尾手动添加一个填充字节:

type TAlarmasRATP = packed record
   Funcion   : Word;
   Instancia : Byte;
   Err_0     : Word;
   Err_1     : Word;
   Padding   : Byte;  // Unused
end;
Run Code Online (Sandbox Code Playgroud)