记录的 Ada pragma Pack 或 Alignment 属性?
Ada pragma Pack or Alignment attribute for Records?
刚刚第一次发现对齐问题,我不确定哪种方法是 best/safest 处理它们的方法。我有一个记录,我正在序列化以通过 Stream 发送,反之亦然,因此它必须符合接口规范并且不包含填充。
给出示例记录:
type MyRecord is record
a : Unsigned_8;
b : Unsigned_32;
end record;
默认情况下这需要 8 个字节,但我可以使用 2 种方法删除包装:
for MyRecord'Alignment use 1;
或
pragma Pack (MyRecord);
我发现了一些与 C 示例相关的问题,但未能找到关于哪种方法最合适、如何确定使用哪种方法或它们是否等效的明确答案?
更新
当我在我的 'real' 代码而不是一个基本示例上尝试这两种方法时,我发现 Alignment 属性实现了我正在寻找的东西。 pragma Pack 显着减小了大小,尚未确认,但我认为它已经打包了我正在使用的许多枚举类型,覆盖了应用于每种类型的“Size use 8”属性。
我想你想要记录表示子句,如果你想要完全控制:
for MyRecord'Size use 40;
for MyRecord use record
a at 0 range 0 .. 7;
b at 1 range 0 .. 31;
end record;
(或者类似的,我可能搞砸了这里的一些索引)。
注意:根据 Simon
的评论编辑
对于Streams you could leave MyRecord
without any representation clauses and use the default MyRecord’Write
and MyRecord’Read
; ARM 13.13.2(9)来说
For elementary types, Read reads (and Write writes) the number of stream elements implied by the Stream_Size for the type T; the representation of those stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in canonical order, which is last dimension varying fastest for an array (unless the convention of the array is Fortran, in which case it is first dimension varying fastest), and positional aggregate order for a record.
GNAT 实现(可能还有其他实现)的一个可能缺点是 ’Write
和 ’Read
调用每一端都调用底层网络软件。通常这不是问题(除了可能的低效率),但如果您使用 TCP_NODELAY
(或更糟的是 UDP),这 不是 您正在寻找的行为。
重载 ’Write
会回到您原来的问题(但至少它仅限于重载过程,因此程序的其余部分可以处理正确对齐的数据)。
为此我使用了内存流(尤其是 UDP 情况); ’Write
到内存流,然后将 Stream_Element_Array
发送到套接字。一个例子是 ColdFrame.Memory_Streams
(.ads, .adb).
刚刚第一次发现对齐问题,我不确定哪种方法是 best/safest 处理它们的方法。我有一个记录,我正在序列化以通过 Stream 发送,反之亦然,因此它必须符合接口规范并且不包含填充。
给出示例记录:
type MyRecord is record
a : Unsigned_8;
b : Unsigned_32;
end record;
默认情况下这需要 8 个字节,但我可以使用 2 种方法删除包装:
for MyRecord'Alignment use 1;
或
pragma Pack (MyRecord);
我发现了一些与 C 示例相关的问题,但未能找到关于哪种方法最合适、如何确定使用哪种方法或它们是否等效的明确答案?
更新
当我在我的 'real' 代码而不是一个基本示例上尝试这两种方法时,我发现 Alignment 属性实现了我正在寻找的东西。 pragma Pack 显着减小了大小,尚未确认,但我认为它已经打包了我正在使用的许多枚举类型,覆盖了应用于每种类型的“Size use 8”属性。
我想你想要记录表示子句,如果你想要完全控制:
for MyRecord'Size use 40;
for MyRecord use record
a at 0 range 0 .. 7;
b at 1 range 0 .. 31;
end record;
(或者类似的,我可能搞砸了这里的一些索引)。
注意:根据 Simon
的评论编辑对于Streams you could leave MyRecord
without any representation clauses and use the default MyRecord’Write
and MyRecord’Read
; ARM 13.13.2(9)来说
For elementary types, Read reads (and Write writes) the number of stream elements implied by the Stream_Size for the type T; the representation of those stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in canonical order, which is last dimension varying fastest for an array (unless the convention of the array is Fortran, in which case it is first dimension varying fastest), and positional aggregate order for a record.
GNAT 实现(可能还有其他实现)的一个可能缺点是 ’Write
和 ’Read
调用每一端都调用底层网络软件。通常这不是问题(除了可能的低效率),但如果您使用 TCP_NODELAY
(或更糟的是 UDP),这 不是 您正在寻找的行为。
重载 ’Write
会回到您原来的问题(但至少它仅限于重载过程,因此程序的其余部分可以处理正确对齐的数据)。
为此我使用了内存流(尤其是 UDP 情况); ’Write
到内存流,然后将 Stream_Element_Array
发送到套接字。一个例子是 ColdFrame.Memory_Streams
(.ads, .adb).