将别名记录数组传递给过程
Passing array of aliased records to a procedure
在 Ada 2012 中,我希望在声明的数组中有一个链表,而不是分配的。我想通过程序设置链接指针。
我已将我的程序简化为以下演示我想要使用的原理的程序,但我无法在 Raspi 上的 Gnat 4.9.2 (Debian Jessie) 运行 中编译它...
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Ch'First .. Ch'Last - 1 loop
Ch (I).Next := Ch (I + 1)'Access; -- ERROR HERE
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
我收到此编译器错误:
“非局部指针不能指向局部对象”在上面指示的行。
我知道我正在尝试做一些有点奇怪的事情,但我计划有一些其他函数,这些函数根据我传递这个单元格数组的过程以不同的方式(向后或随机等)执行链接到.
如何修复此代码以使其通过编译?不太了解这个(我还是个新手,但很享受学习的过程)。
由于您实际上并未分配和释放内存,因此看不到需要指针。我会通过做这样的事情来实现相同的功能:
procedure Arr is
type Cell_Index is new Integer range 0 .. 100;
subtype Valid_Cell_Index is Cell_Index range 1 .. Cell_Index'Last;
type Cell is
record
Number : Integer := 0;
Next : Cell_Index := 0;
end record;
type Chain is array (Valid_Cell_Index) of Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Valid_Cell_Index'First .. Valid_Cell_Index'Last - 1 loop
Ch (I).Next := I+1;
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
这样您仍然可以使用 Next 作为同一数组的索引,并且可以使用您想要的任何链接模式预加载您的数组。
不使用 ’Access
,而是使用 ’Unrestricted_Access
。这是 one of GNAT’s “implementation-defined” attributes:
The Unrestricted Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute.
最后我想通了。以下代码是 OP 中代码的修改版本。它做了我最初想要的,没有做任何不愉快的事情......
with Ada.Integer_Text_IO, Ada.Text_IO;
use Ada.Integer_Text_IO, Ada.Text_IO;
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
type Chain_Ptr is access all Chain;
procedure Make_Links (CP : in out Chain_Ptr);
procedure Make_Links (CP : in out Chain_Ptr) is
begin
for I in CP'First .. CP'Last - 1 loop
CP.all (I).Next := CP.all (I + 1)'Access;
end loop;
end Make_Links;
My_Chain : aliased Chain;
My_CP : Chain_Ptr := null;
My_C : Cell_Ptr := null;
begin
My_CP := My_Chain'Access;
Make_Links (My_CP);
-- verify that the code works by writing values into the array
for I in My_Chain'Range loop
My_Chain (I).Number := 1000 * I;
end loop;
-- and read them back out using the pointer links
My_C := My_Chain (My_Chain'First)'Access;
while My_C /= null loop
Put (My_C.Number);
Put_Line ("");
My_C := My_C.Next;
end loop;
end Arr;
我没有直接传递数组,而是传递了一个指向数组的指针,Gnat 似乎对此很满意。我 认为 我之前尝试做的事情被过程参数的 "pass by copy" 规则破坏了。
在 Ada 2012 中,我希望在声明的数组中有一个链表,而不是分配的。我想通过程序设置链接指针。
我已将我的程序简化为以下演示我想要使用的原理的程序,但我无法在 Raspi 上的 Gnat 4.9.2 (Debian Jessie) 运行 中编译它...
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Ch'First .. Ch'Last - 1 loop
Ch (I).Next := Ch (I + 1)'Access; -- ERROR HERE
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
我收到此编译器错误: “非局部指针不能指向局部对象”在上面指示的行。
我知道我正在尝试做一些有点奇怪的事情,但我计划有一些其他函数,这些函数根据我传递这个单元格数组的过程以不同的方式(向后或随机等)执行链接到.
如何修复此代码以使其通过编译?不太了解这个(我还是个新手,但很享受学习的过程)。
由于您实际上并未分配和释放内存,因此看不到需要指针。我会通过做这样的事情来实现相同的功能:
procedure Arr is
type Cell_Index is new Integer range 0 .. 100;
subtype Valid_Cell_Index is Cell_Index range 1 .. Cell_Index'Last;
type Cell is
record
Number : Integer := 0;
Next : Cell_Index := 0;
end record;
type Chain is array (Valid_Cell_Index) of Cell;
procedure Make_Links (Ch : in out Chain);
procedure Make_Links (Ch : in out Chain) is
begin
for I in Valid_Cell_Index'First .. Valid_Cell_Index'Last - 1 loop
Ch (I).Next := I+1;
end loop;
end Make_Links;
My_Chain : Chain;
begin
Make_Links (My_Chain);
end Arr;
这样您仍然可以使用 Next 作为同一数组的索引,并且可以使用您想要的任何链接模式预加载您的数组。
不使用 ’Access
,而是使用 ’Unrestricted_Access
。这是 one of GNAT’s “implementation-defined” attributes:
The Unrestricted Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute.
最后我想通了。以下代码是 OP 中代码的修改版本。它做了我最初想要的,没有做任何不愉快的事情......
with Ada.Integer_Text_IO, Ada.Text_IO;
use Ada.Integer_Text_IO, Ada.Text_IO;
procedure Arr is
type Cell;
type Cell_Ptr is access all Cell;
type Cell is
record
Number : Integer := 0;
Next : Cell_Ptr := null;
end record;
type Chain is array (1 .. 100) of aliased Cell;
type Chain_Ptr is access all Chain;
procedure Make_Links (CP : in out Chain_Ptr);
procedure Make_Links (CP : in out Chain_Ptr) is
begin
for I in CP'First .. CP'Last - 1 loop
CP.all (I).Next := CP.all (I + 1)'Access;
end loop;
end Make_Links;
My_Chain : aliased Chain;
My_CP : Chain_Ptr := null;
My_C : Cell_Ptr := null;
begin
My_CP := My_Chain'Access;
Make_Links (My_CP);
-- verify that the code works by writing values into the array
for I in My_Chain'Range loop
My_Chain (I).Number := 1000 * I;
end loop;
-- and read them back out using the pointer links
My_C := My_Chain (My_Chain'First)'Access;
while My_C /= null loop
Put (My_C.Number);
Put_Line ("");
My_C := My_C.Next;
end loop;
end Arr;
我没有直接传递数组,而是传递了一个指向数组的指针,Gnat 似乎对此很满意。我 认为 我之前尝试做的事情被过程参数的 "pass by copy" 规则破坏了。