1

スペースを節約するために3つの異なる配列を使用する代わりに、異なるアクションに同じ配列を使用しようとしています。たとえば、私のプログラムスペースの特定の部分では、1..5が使用されておらず、別の部分のスペース3..8は使用されていません。

キーワードの名前を変更するとうまくいきますか?このようなもの?

type SharedArray is array (integer range 1..10) of integer;
array1: SharedArray;
array2: SharedArray renames array1(1..5);

私が正しければ、array2はまったく新しい配列ではなく、値が変更されるたびにarray1を参照するだけですか?

4

3 に答える 3

2

ここで最初に頭に浮かんだのは、「いいえ、これはうまくいきません」でした。しかし、それから私はGNAT GPL2012でこれを書きました:

with Text_IO; use Text_IO;

procedure Ren_Test is

   type Shared_Array is array (Integer range 1 .. 10) of Integer;

   Array1 : Shared_Array := (others => 42);
   Array2 : Shared_Array renames Array1(1..5);

begin
   Put_Line("Array1 range: " & Integer'Image(Array1'First) & " .." 
          & Integer'Image(Array1'Last));
   Put_Line("Array2 range: " & Integer'Image(Array2'First) & " .." 
          & Integer'Image(Array2'Last));
   New_Line;
   Put_Line("Dump Array1");
   for I in Array1'Range loop
      Put(Integer'Image(Array1(I)));
      if I /= Array1'Last then
         Put(",");
      end if;
   end loop;
   New_Line(2);


   Put_Line("Dump and modify renaming Array2");
   for I in Array2'Range loop
      Put(Integer'Image(Array2(I)));
      if I /= Array2'Last then
         Put(",");
      end if;
      Array1(I) := Array1(I) + 17;
   end loop;
   New_Line(2);

   Put_Line("Redump Array1");
   for I in Array1'Range loop
      Put(Integer'Image(Array1(I)));
      if I /= Array1'Last then
         Put(",");
      end if;
   end loop;
   New_Line;
end Ren_Test;

それを実行すると私が得ます:

[35] Marc say: ./ren_test
Array1 range:  1 .. 10
Array2 range:  1 .. 5

Dump Array1
 42, 42, 42, 42, 42, 42, 42, 42, 42, 42

Dump and modify renaming Array2
 42, 42, 42, 42, 42

Redump Array1
 59, 59, 59, 59, 59, 42, 42, 42, 42, 42

これは、主に、制約された配列を宣言されたサイズよりも小さくスライスした結果、Constraint_Errorが発生すると予想したためです。したがって、これが合法的なコードであるかどうかはわかりません。GNATGPL2012が問題なくコンパイルおよび実行されることは知っています。

Shared_Arrayが制約のない配列である場合、私ははるかに快適です。

   type Shared_Array is array (Integer range <>) of Integer;

   Array1 : Shared_Array (1..10) := (others => 42);
   Array2 : Shared_Array renames Array1(1..5);

後者は、標準に準拠することを期待しています。最初の、制約された形式... IMHO、iffy。(ただし、これを確認するのは言語弁護士に任せます。)

于 2012-10-10T00:34:18.857 に答える
0

同じメモリを異なる識別子で使用する場合は、アクセスタイプを使用できます。ただし、これは添え字のマッピングには何もしません。

procedure Array_Alias is
   type Shared_Array_Type is array (1 .. 10) of Integer;
   Array_1 : aliased Shared_Array_Type := (others => 0);
   Array_2 : access Shared_Array_Type := Array_1'Access;
begin

   Array_1(1 .. 3) := (1, 2, 3);
   Array_2(5 .. 8) := (others => -1);
   for Index in 1 .. 10 loop
      Text_IO.Put(Array_1(Index)'Img & " ");
   end loop;
   Text_IO.New_Line;

end Array_Alias;

生産:

 1  2  3  0 -1 -1 -1 -1  0  0 

編集:匿名アクセスタイプがAda2005で追加されました。Ada95の場合、配列型へのアクセス型を宣言する必要があります。

type Access_Shared_Array_Type is access all Shared_Array_Type;
Array_2 : Access_Shared_Array_Type := Array_1'Access;
于 2012-10-10T02:53:47.680 に答える
0

明示的に求めているのはエイリアシングです。変数のエイリアシングは、貧しい人間を混乱させる傾向があり、非常に微妙で見つけにくいバグにつながる可能性があります。これにより、コードのバグが発生しやすくなり、対処するのにストレスがかかります。要するに、エイリアシングは悪です。

また、この場合、うまく設計された言語の魔法のおかげで、それは完全に不必要です。あなたがしなければならないのは、バッファを異なる方法で処理するコードを異なるルーチンに分割することです。それらのルーチンが知る限り、それらは渡されたのと同じ大きさの配列のみを処理します。たとえば、私は次の短いコードを書きました。

with Ada.Text_Io;

procedure Ada_Slice is

   type Integer_Array is array (Natural range <>) of Integer;
   Integer_Buffer : Integer_Array (1..10) := (1,2,3,4,5,6,7,8,9,10);

   procedure Magnify (Buffer : in out Integer_Array) is
   begin
      for I in Buffer'Range loop
         Buffer(I) := Buffer(I) * 10;
      end loop;
   end Magnify;

   procedure Swap (Front : in out Integer_Array;
                   Back : in out Integer_Array) is
      Scratch : Integer;
   begin
      for I in Front'Range loop
         Scratch := Front(I);
         Front(I) := Back(Back'First + (I - Front'First));
         Back(Back'First + (I - Front'First)) := Scratch;
      end loop;
   end Swap;

begin

   Magnify(Integer_Buffer(6..10));
   Swap (Integer_Buffer(1..2), Integer_Buffer(9..10));

   for I in Integer_Buffer'range loop
      Ada.Text_Io.Put (Integer'Image(Integer_Buffer(I)) & ",");
   end loop;
   Ada.Text_Io.New_Line;

end Ada_Slice;

実行すると、出力はもちろん次のようになります。

90、100、3、4、5、60、70、80、1、2

(末尾のコンマを修正することは、読者の練習問題として残されています)

于 2012-10-10T18:57:06.547 に答える