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

San*_*pta 1 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; 
Run Code Online (Sandbox Code Playgroud)

Kei*_*son 5

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

如果您确实想对 Ada 访问类型执行 C 风格的指针算术,则可以使用 generic 包System.Address_To_Access_Conversions将对象指针类型转换为System.Address,并使用该System.Storage_Elements包对值执行类似 C 的算术System.Address

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

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

int arr[10];
int *ptr = &arr[0];
Run Code Online (Sandbox Code Playgroud)

指针值ptr + 3指向arr[3],它是int超过指向的位置(不一定是ptr三个字节)的三个大小的内存块。和运算符处理存储元素中的偏移量(很可能相当于 C 的“字节”)。"+""-"System.Storage_Elements

因此,如果您有一个 Ada指针,嗯,我的意思是访问值,它引用Integers 数组的一个元素,那么前进到该数组的一个元素需要:

  • 使用System.Address_To_Access_Conversions将访问类型转换为System.Address;
  • 使用重载"+"运算符 in将in 字节( )System.Storage_Elements的大小添加到值中;和Integer Integer'Max_Size_In_Storage_ElementsSystem.Address
  • 再次使用System.Address_To_Access_ConversionsSystem.Address值转换回您的访问类型。

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

但很可能您不需要Ada 中进行指针运算。C核心语言有指针运算;它甚至根据指针算术定义数组索引。艾达没有。在 Ada 中执行指针算术几乎没有充分的理由。只需让数组成为数组,然后让编译器找出如何生成访问其元素的最佳代码即可。(该代码可能涉及 CPU 指令级别的指针算术。)

  • 您可以使用“t'Max_Size_In_Storage_Elements”来找出“t”占用了多少字节。 (2认同)

Mar*_*c C 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;
Run Code Online (Sandbox Code Playgroud)

运行它:

C:\Ada\Sandbox\access_pointer_arithmetic
 2
 5
 7
 9
 5
Run Code Online (Sandbox Code Playgroud)

该包提供单个递增/递减,ptrdiff_t的加法和减法,以及终止符指定和固定长度元素数组检索.

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