我怎样才能增加一个访问类型,就好像它是一个 C 指针一样?

How can I increment an access type as if it were a C pointer?

如何在 C 中递增访问类型的地址,如指针?我是 Ada 的新手...

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; 

更新: 我刚刚发现有一个标准包 Interfaces.C.Pointers 直接支持 C 风格的指针运算,现在我看到 涵盖了它的用法。您可能会忽略我的回答,它讨论了如果 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],这是 ptr 指向 之后的三个 int 大小的内存块not 一定是三个字节。 System.Storage_Elements 中的 "+""-" 运算符处理存储元素中的偏移量(这很可能等同于 C 的 "bytes")。

所以如果你有一个 Ada 指针,嗯,我的意思是访问值,它指的是 Integer 数组的一个元素,然后前进到该数组的下一个 元素要求:

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

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

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

实例化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

此包提供单个increment/decrement、ptrdiff_t的加法和减法,以及指定终止符和定长元素数组的检索。

(注意 运行 数组的末尾...:-)