1

我在创建粗指针时遇到问题。我当前的声明集如下所示:

type Index_Typ is mod 20; -- will be larger in real life
type Data_Buffer_Typ is array (Index_Typ range <>) of Integer; --unconstrained array type
type Data_Buffer_Ptr is access all Data_Buffer_Typ; -- a thick pointer, contains the bounds of array subtype pointed to and address..

Data_Buffer : aliased Data_Buffer_Typ (Index_Typ) := (others => 0); -- this is private
type Result_Typ is (Ok, Overflow, Null_Pointer);

   procedure Retrieve (Index    : in     Index_Typ;
                       Len      : in     Index_Typ;
                       Data_Ptr :    out Data_Buffer_Ptr;
                       Result   :    out Result_Typ) is
   begin
     -- assuming range checks are ok, what goes here ?
   end Retrieve;

所以如果我声明:

Ptr : Data_Buffer_Ptr := null;

并调用Retreive (2,3, Ptr,Result);我如何最终得到一个指向元素 2,3 和 4 的指针Data_Buffer

笔记:

  • 是的,我知道传递一个数组切片可能无论如何都会作为一个指针来完成,但是我们想要显式地使用指针,而不是隐式地使用指针(而不是我的选择!)。
  • 是的,我已经尝试过了,我通常会收到:(object subtype must statically match designated subtype)错误消息..
  • 尽可能new避免使用。
4

1 回答 1

1

这对我有用,虽然我不得不说它是令人厌恶的!注意 中的组件顺序Fat_Pointer,这与我开始时的顺序相反,以及这台 64 位机器上记录的大小(我将 rep 子句放入以使顺序明确,没有它也可以正常工作)。另外,我认为您坚持使用new.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Conversion;
with System;
procedure Fat is
   type Index_Typ is mod 20;
   type Data_Buffer_Typ is array (Index_Typ range <>) of Integer;
   type Data_Buffer_Ptr is access all Data_Buffer_Typ;
   Data_Buffer : aliased Data_Buffer_Typ (Index_Typ) := (others => 0);
   type Result_Typ is (Ok, Overflow, Null_Pointer);

   procedure Retrieve (Index    : in     Index_Typ;
                       Len      : in     Index_Typ;
                       Data_Ptr :    out Data_Buffer_Ptr;
                       Result   :    out Result_Typ)
   is
      type Bound is (Lower, Upper);
      type Bounds is array (Bound) of Index_Typ;
      type Bounds_P is access Bounds;
      type Fat_Pointer is record
         The_Data : System.Address;
         The_Bounds : Bounds_P;
      end record;
      for Fat_Pointer use record
         The_Data at 0 range 0 .. 63;
         The_Bounds at 8 range 0 .. 63;
      end record;
      function To_Data_Buffer_Ptr
      is new Ada.Unchecked_Conversion (Fat_Pointer, Data_Buffer_Ptr);
      Answer : constant Fat_Pointer
        := (The_Bounds => new Bounds'(Lower => Index,
                                      Upper => Index + Len - 1),
            The_Data => Data_Buffer (Index)'Address);
   begin
      Result := Ok;
      Data_Ptr := To_Data_Buffer_Ptr (Answer);
   end Retrieve;

   Ptr : Data_Buffer_Ptr := null;
   Result : Result_Typ;

begin
   for J in Data_Buffer'Range loop
      Data_Buffer (J) := Integer (J);
   end loop;

   Retrieve (2, 3, Ptr, Result);

   for J in Ptr'Range loop
      Put_Line (J'Img & " => " & Ptr (J)'Img);
   end loop;
end Fat;
于 2013-03-19T11:04:59.530 回答