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 GPL 2012 写了这个:

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。所以我不知道这是合法代码,我知道 GNAT GPL 2012 可以毫无问题地编译和运行它。

当 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);

后者我希望符合标准。第一个,受约束的形式......恕我直言,不确定。(但我会把它留给语言律师来验证这一点。)

于 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 回答