1

我正在开发一个程序,该程序需要将一个巨大的多层阵列写入几个较小的缓冲区。我希望通过使用 unchecked_conversion 将多层阵列展平为单层阵列,然后对阵列进行切片来做到这一点。为了从内存中恢复它,我想将这些部件重新添加到 order 中并将它们 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 会做这种事情,还是会破坏原始数组以使其无法恢复?谢谢!

4

2 回答 2

2

是的,因为这些是静态大小的数组,所以 Unchecked_Conversion 可以工作。

(但这是一种相当不寻常的方法。如果我们对您实际尝试做的事情有所了解,可能会建议使用更合适的数据结构。)

另一种方法是别名(警告,未编译):

TL     : Top_Level;

Buffer : Monolithic_Array;
for Buffer'Address use TL'Address;

只要您以与传输源缓冲区段相同的顺序填充接收缓冲区,它就应该重新组装得很好。

于 2013-10-01T17:48:58.807 回答
1

以下是一些如何进行此类转换的示例;它还遍历转换函数集并测试它们的正确性。实现 aStream_Convert留给读者作为练习。(来自程序员的翻译:“我懒得做。”)

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;
于 2013-10-02T01:33:24.483 回答