刚刚发现对齐问题我不确定哪种方法是处理它们的最佳/最安全的方法。我有一个记录,我串行通过流发送,反之亦然,所以它必须符合接口规范,不包含填充。
给出示例记录:
type MyRecord is record
a : Unsigned_8;
b : Unsigned_32;
end record;
默认情况下需要8个字节,但我可以使用2种方法删除打包:
for MyRecord'Alignment use 1;
或
pragma Pack (MyRecord);
我发现了一些与C示例有关的问题,但未能找到最合适的方法,如何确定使用哪种方法或它们是否相同?
更新
当我尝试使用“真实”代码而不是基本示例时,我发现Alignment属性实现了我想要的。 pragma Pack显着减小了大小,但没有确认,但我认为它已经打包了我正在使用的许多枚举类型,覆盖了应用于每种类型的'size use 8属性。
答案 0 :(得分:4)
对于Streams,您可以保留MyRecord
而不包含任何陈述条款,并使用默认的MyRecord’Write
和MyRecord’Read
; ARM 13.13.2(9)说
对于基本类型,Read读取(和写入)Stream_Size为类型T隐含的流元素的数量;这些流元素的表示是实现定义的。对于复合类型,每个组件的Write或Read属性以规范顺序调用,这是数组最快变化的最后一个维度(除非数组的约定是Fortran,在这种情况下它是第一个维度变化最快的),以及位置记录的总订单。
GNAT实现(可能是其他实现)的一个可能的缺点是’Write
和’Read
调用每个结束调用底层网络软件。通常情况下,这不是问题(除了可能的低效率),但如果你使用的是TCP_NODELAY
(或者更糟的是UDP),那么不是你正在寻找的行为。
重载’Write
会导致回到原来的问题(但至少它只限于重载过程,因此程序的其余部分可以处理正确对齐的数据)。
我为此使用了内存流(尤其是UDP的情况); ’Write
到内存中的流,然后将Stream_Element_Array
发送到套接字。一个例子是ColdFrame.Memory_Streams
(.ads,.adb)。
答案 1 :(得分:1)
如果您想要完全控制,我认为您需要记录表示条款:
for MyRecord'Size use 40;
for MyRecord use record
a at 0 range 0 .. 7;
b at 1 range 0 .. 31;
end record;
(或者其他一些,我可能在这里搞砸了一些指数)。
注意:根据Simon的评论进行编辑