如何增加访问类型,就像它是C指针一样?

时间:2015-01-07 18:12:49

标签: ada

如何在C中增加像指针一样的访问类型的地址?我是阿达的新手......

procedure main is
  type myarr is array(1..5)of integer; --creating array of 5 integer.
  myarr_var:aliased myarr:=(2,5,7,9,0); --setting 5 values
  type my_access is access all myarr; --creating access type (pointer)
  var:my_access:=myarr_var'access;  --holding address of 5 integer
begin;
  -- since var holds the address of myarr_var now i want to increment
  -- the address by adding 1 to print next value (5) as we do in c?

  put((var+1).all); --???
  -- i know this is bad but how to increment its base address of 
  -- var(pointer) so that it will point to next element 5?

end main; 

2 个答案:

答案 0 :(得分:5)

实例化Interfaces.C.Pointers以在Ada中执行C风格的指针算法。

最好用例子解释:

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C.Pointers;

procedure Access_Pointer_Arithmetic is

   type Myarr_Indices is range 1 .. 5;
   type Myarr is array (Myarr_Indices range <>) of aliased Integer;

   Myarr_Terminator : constant Integer := 0;

   package Myarr_Pointer_Arithmetic is new Interfaces.C.Pointers
     (Myarr_Indices, Integer, Myarr, Myarr_Terminator);

   use Myarr_Pointer_Arithmetic;

   Myarr_Var : aliased Myarr := (2, 5, 7, 9, 0);

   Var : Myarr_Pointer_Arithmetic.Pointer :=
              Myarr_Var(Myarr_Var'First)'access;

begin
   Put_Line(Integer'Image(Var.all));
   Increment(Var);
   Put_Line(Integer'Image(Var.all));
   Increment(Var);
   Put_Line(Integer'Image(Var.all));
   Increment(Var);
   Put_Line(Integer'Image(Var.all));

   Var := Var - 2;
   Put_Line(Integer'Image(Var.all));
end Access_Pointer_Arithmetic;

运行它:

C:\Ada\Sandbox\access_pointer_arithmetic
 2
 5
 7
 9
 5

该软件包提供单个递增/递减,ptrdiff_t的加法和减法,以及终结器指定和固定长度元素数组检索。

(介意运行阵列结束......: - )

答案 1 :(得分:4)

更新:我刚发现那里有一个直接支持C风格指针算法的标准包Interfaces.C.Pointers,现在我看到Marc C.'s accepted answer涵盖了它用法。您可以忽略我的答案,该答案讨论了如果Interfaces.C.Pointers不存在(在早期版本的语言中,它没有),您可以在Ada中进行指针算术。

如果确实希望对Ada访问类型执行C风格的指针算法,则可以使用通用包System.Address_To_Access_Conversions将对象指针类型转换为System.Address,以及System.Storage_Elements包对System.Address值执行类C算术。

请注意,目标对象类型是System.Address_To_Access_Conversions通用包的参数。包本身定义了访问类型。您无法定义自己的访问类型并使用它(至少不能直接使用)。

请记住,C指针算术是以指向对象的大小为单位定义的。所以给出:

int arr[10];
int *ptr = &arr[0];

指针值ptr + 3指向arr[3],这是三个int大小的内存块,超过ptr不必须三个字节。 "+"中的"-"System.Storage_Elements运算符可以处理存储元素中的偏移量(很可能等同于C&#34;字节&#34;)。

所以如果你有一个Ada 指针,嗯,我的意思是访问值,它指的是Integer s数组的元素,然后前进到 next < / em>该数组的元素需要:

  • 使用System.Address_To_Access_Conversions将访问类型转换为System.Address;
  • 使用"+"中的重载System.Storage_Elements运算符将Integer 的字节数Integer'Max_Size_In_Storage_Elements)添加到{{1}价值;和
  • 再次使用System.AddressSystem.Address_To_Access_Conversions值转换回您的访问类型。

另一种方法可能是编写C代码来执行您需要的任何指针算法,并使用System.Address从您的Ada程序中调用该代码。

但很有可能你不需要在Ada中进行指针运算。 C在核心语言中有指针算术;它甚至根据指针算法定义了数组索引。阿达没有。在Ada中执行指针算法很少是一个很好的理由。让数组成为数组,让编译器弄清楚如何生成访问其元素的最佳代码。 (该代码可能涉及CPU指令级别的指针运算。)