我希望创建一个打包记录,它可以容纳一个长度从5到50个不同的数组。是否可以这样做,以便记录可以打包没有浪费的空间?我将在创建记录时知道阵列中有多少元素。
-- the range of the array
type Array_Range_T is Integer range 5 .. 50;
-- the array type
type Array_Type_T is array range (Array_Range_T) of Integer;
-- the record
type My_Record_T (Array_Length : Integer := 5) is
record
-- OTHER DATA HERE
The_Array : Array_Type_T(Array_Length);
end record;
-- Pack the record
for My_Record_T use
record
-- OTHER DATA
The_Array at 10 range 0 .. Array_Length * 16;
end record;
for My_Record_T'Size use 80 + (Array_Length * 16);
这显然不会编译,但显示了我想要做的精神。如果可能的话,我希望将数组的长度保持在记录之外。
谢谢!
答案 0 :(得分:5)
Ada真的没有办法按照你要求的方式来表示记录。但是,由于您的关注事实并非与记录在内存中的表示方式有关,而在于它如何传输到套接字,您可能不必担心记录表示条款。
相反,您可以定义自己的Write
例程:
procedure Write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in My_Record_T);
for My_Record_T'Write use Write;
或者,我相信这将在Ada 2012中有效:
type My_Record_T is record
...
end record
with Write => Write;
procedure Write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in My_Record_T);
然后身体看起来像
procedure Write (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
Item : in My_Record_T) is
begin
-- Write out the record components, EXCEPT Array_Length and The_Array.
T1'Write (Stream, Item.F1); -- F1 is a record field, T1 is its type
T2'Write (Stream, Item.F2); -- F2 is a record field, T2 is its type
...
-- Now write the desired data
declare
Data_To_Write : Array_Type_T (1 .. Item.Array_Length)
renames Item.The_Array (1 .. Item.Array_Length);
-- I'm assuming the lower bound is 1, but if not, adjust your code
-- accordingly
begin
Array_Type_T'Write (Stream, Data_To_Write);
-- Note: using 'Write will write just the data, without any bound
-- information, which is what you want.
end;
end Write;
如果需要打包其他组件,这将无法工作,例如如果要将字节写入包含一个3位记录组件和一个5位记录组件的套接字。如果有必要,我不认为内置'Write
属性会为您做到这一点;你可能需要做自己的苦恼,或者你可能会变得棘手并定义一个Stream_Elements
数组并使用Address
子句或方面来定义一个覆盖其余记录的数组。但我不会使用叠加方法,除非我100%确定套接字另一端的读者是使用完全相同类型定义的Ada程序。
注意:我还没有对此进行测试。
答案 1 :(得分:0)
我不确定我完全理解你想要达到的目标,但是你不能做这样的事情
-- the range of the array
type Array_Range_T is range 1 .. 50;
-- the array type
type Array_Type_T is array (Array_Range_T range <>) of Integer;
Array_Length : constant := 5; --5 elements in the array
-- the record
type My_Record_T is
record
-- OTHER DATA HERE
The_Array : Array_Type_T (1 .. Array_Length);
end record;
-- Pack the record
for My_Record_T use
record
-- OTHER DATA
The_Array at 0 range 0 .. (Array_Length * Integer'Size) - 1 ;
end record;
for My_Record_T'Size use (Array_Length * Integer'Size);