我正在开发一个程序,需要将一个巨大的多层数组写入几个较小的缓冲区。我希望通过使用unchecked_conversion将多层数组展平为单层数组,然后切片数组来实现此目的。要从内存中恢复它,我想将这些部分重新按顺序附加,并将Unchecked_Conversion重新恢复到原始状态。
原始实现看起来像这样:
-- array of up to 500 (most likely 100 - 200 though)
type Bottom_Level is array(1 .. 500) of Integer;
-- colors type
type Colors is (red, blue, green, purple);
for Colors use (red => 1, blue => 2, green => 3, purple => 4);
-- Middle Level Array
type Middle_Level is array(Colors) of Bottom_Level;
-- shapes type
type Shapes is (square, triangle, circle);
for Shapes use (square => 1, triangle => 2, circle => 3);
-- Top Level Array
type Top_Level is array(Shapes) of Middle_Level;
我想将其压缩成如下数组:
type Monolithic_Array is Array (1 .. 6000) of Integer;
Unchecked_Conversion是否可以执行此类操作,还是会破坏原始数组以使其无法恢复?谢谢!
答案 0 :(得分:2)
是的,因为这些是静态大小的数组,Unchecked_Conversion会起作用。
(但这是一种相当不寻常的方式。如果我们知道你实际上想要做什么,可能会建议更贴切的数据结构。)
另一种方法是别名(警告,未编译):
TL : Top_Level;
Buffer : Monolithic_Array;
for Buffer'Address use TL'Address;
只要以与传输源缓冲区段相同的顺序填充接收缓冲区,它就应该重新组合好。
答案 1 :(得分:1)
以下是一些如何进行此类转换的示例;它还遍历转换函数集并测试它们的正确性。实施Stream_Convert
是留给读者的练习。 (来自programmerese的翻译:“我懒得去做。”)
Pragma Ada_2012;
With
Ada.Streams.Stream_IO,
Ada.Text_IO,
Interfaces;
Procedure Test_Arrays is
Type Byte is new Interfaces.Unsigned_8;
Type MD is Array (1..3, 1..3) of Byte;
Type SD is Array (1..MD'Size/MD'Component_Size) of Byte;
-- INDEX-CALCULATION METHOD
Function Mod_Convert( Input : SD ) return MD is
subtype Primary is Integer range MD'Range(1); --'
subtype Secondary is Integer range MD'Range(2); --'
begin
return Result : MD do
for Index_1 in Primary loop
for Index_2 in Secondary loop
Result(Index_1, Index_2):=
Input( Integer'Pred(Index_1)*Primary'Last + Index_2 );
end loop;
end loop;
end return;
end Mod_Convert;
Function Mod_Convert( Input : MD ) return SD is
subtype Primary is Integer range MD'Range(1); --'
subtype Secondary is Integer range MD'Range(2); --'
begin
return Result : SD do
for Index in Result'Range loop --'
declare
Index_2 : Integer renames Integer'Succ( Integer'Pred(Index) mod Secondary'Last); --'
Index_1 : Integer renames Integer'Succ((Index-Index_2) / Primary'Last);
begin
Result(Index) := Input( Index_1, Index_2 );
end;
end loop;
end return;
end Mod_Convert;
-- OVERLAY METHOD
Function Overlay_Convert( Input : MD ) return SD is
Result : SD with Import, Convention => Ada, Address => Input'Address; --'
begin
Return Result;
end Overlay_Convert;
Function Overlay_Convert( Input : SD ) return MD is
Result : MD with Import, Convention => Ada, Address => Input'Address; --'
begin
Return Result;
end Overlay_Convert;
-- Print out MD-array.
Procedure Print( Input : MD ) is
Use Ada.Text_IO;
begin
for Index_1 in MD'Range(1) loop --'
for Index_2 in MD'Range(2) loop --'
Put( Byte'Image(Input(Index_1, Index_2)) ); --'
end loop;
New_Line;
end loop;
end Print;
-- Print out SD-array.
Procedure Print( Input : SD ) is
Use Ada.Text_IO;
begin
for Item of Input loop
Put( Byte'Image(Item) ); --'
end loop;
New_Line;
end Print;
Type Conversins is ( mod_type, overlay );
type SD_to_MD_Conversion is not null access function(Input : SD) return MD;
type MD_to_SD_Conversion is not null access function(Input : MD) return SD;
type Conversion_Record is record
SD_to_MD : SD_to_MD_Conversion;
MD_to_SD : MD_to_SD_Conversion;
end record;
Conversions_Var : constant Array( Conversins ) of Conversion_Record:=
( mod_type => (Mod_Convert'Access, Mod_Convert'Access),
overlay => (Overlay_Convert'Access, Overlay_Convert'Access)
);
J : Constant SD := ( 9,8,7,6,5,4,3,2,1 );
Begin
for Conversion : Conversion_Record of Conversions_Var loop
declare
J_prime : MD renames Conversion.SD_to_MD( J );
J_doubleprime : SD renames Conversion.Md_to_SD( J_prime );
begin
Print( J );
Print( J_prime );
Print( J_doubleprime );
Ada.Text_IO.New_Line;
if J_doubleprime = J then
Ada.Text_IO.put_line( "Conversion is good." );
else
Ada.Text_IO.put_line( "WARNING: BAD CONVERSION!" );
end if;
end;
end loop;
End Test_Arrays;