1

巨大な多層配列をいくつかの小さなバッファに書き込む必要があるプログラムに取り組んでいます。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 はこの種の処理を行うのでしょうか?それとも、元の配列を破壊して復元できないようにするのでしょうか? ありがとう!

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

このような変換を行う方法の例をいくつか示します。また、一連の変換関数を繰り返し処理し、それらが正しいかどうかをテストします。a の実装Stream_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 に答える