2013-03-18 2 views
1

У меня возникли проблемы с созданием толстого указателя. Мой текущий набор объявлений выглядеть следующим образом:Возвратите жир/толстый указатель как параметр out

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, которого следует избегать.
+0

(a) Если вы должны использовать суффиксы, чтобы указать, что имя обозначает тип, почему бы не использовать '_Type'? или просто '_T'? (b) вы не показываете нам, что 'Result_Typ' (c) являются параметрами' Data_Ptr' и 'Result' действительно' out'? –

+0

@SimonWright (а) стандарты кодирования компании. (b) Result_typ - это перечисление. Не имеет значения, просто указывает, успешна ли операция или почему нет (переполнение конца ошибок типа буфера). c) Да и Да. – NWS

+0

@SimonWright - в (c) вы предполагаете, что 'in out' может быть более уместным? – NWS

ответ

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; 
+0

Спасибо Simon, я принимаю это как доказательство того, что мы не должны попробовать! – NWS

Смежные вопросы