我怎样才能增加一个访问类型,就好像它是一个 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_Conversions
将 System.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的加法和减法,以及指定终止符和定长元素数组的检索。
(注意 运行 数组的末尾...:-)
如何在 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_Conversions
将System.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的加法和减法,以及指定终止符和定长元素数组的检索。
(注意 运行 数组的末尾...:-)