我在Ada95工作,而且我很难搞清楚指针.
我的代码如下所示:
type vector is array (1 .. 3) of integer;
type vector_access is access vector;
my_vec : vector;
procedure test is
pointer : vector_access := my_vec'access;
begin
...
end;
Run Code Online (Sandbox Code Playgroud)
这无法编译指针的定义,说
"'ACCESS的前缀必须是对象的别名视图,或者表示具有非内在调用约定的子程序"
如果我然后将向量本身的定义更改为:
my_vec : aliased vector
Run Code Online (Sandbox Code Playgroud)
它现在返回编译器错误:
"X'ACCESS的预期类型,其中X表示对象的别名视图,必须是一般的访问类型"
在一天结束时,我真正需要的是指向数组中特定项的指针,该位置基于输入参数是动态的.谁能指出我正确的方向?
如果您正在使用GNAT,那么"必须是一般访问类型"之后的错误消息应该为您提供了解决方案:
添加"all"以键入行中定义的"vector_access"...
所以你最终得到:
type Vector_Access is access all Vector;
Run Code Online (Sandbox Code Playgroud)
使用"all"来指定一般访问类型与Ada中的动态内存分配池有关.如果您不关心动态内存分配池,那么请不要担心它,只需在访问类型定义中包含"all"即可.
我不确定这是否是你在一天结束时所寻找的内容的一部分,但是你知道在大多数情况下,Ada的访问(指针)类型用于处理动态分配的内存,对吗?
因此,不是将my_vec指向别名变量,而是动态分配它:
Pointer_2_Dynamic : vector_access := new Vector;
Run Code Online (Sandbox Code Playgroud)
这样,您可以在运行时动态分配所需的对象,并轻松处理可变大小的对象(尽管您需要一个不同的向量定义来实现:
type Dynamic_Vector is array (Natural range <>) of Integer;
type Dynamic_Vector_Access is access Dynamic_Vector;
N : Natural := 10; -- Variable here, but could be a subprogram parameter.
Dyn_Vector : Dynamic_Vector_Access := new Dynamic_Vector(1..N);
Run Code Online (Sandbox Code Playgroud)
好.关于专家Cish编码员的Ada的第一课:Ada参数与Cish参数不同.在C中,(预引用参数)每个参数都相当于一个Ada'in'参数,附加条件是C编译器必须总是愚蠢地传递堆栈上的整个东西,无论它有多大.因此,你可怜的C编码器将它钉入你的大脑,你永远不会将大对象直接传递给子程序,但总是使用指针.
阿达不同.您告诉编译器您希望如何访问参数(只读 - 'in',只写 - 'out'或read write - 'in out').但是,这与参数的传递方式无关.传递mechanisim的参数取决于编译器,编译器将选择最有效的方法来完成它.实际上,在几乎所有平台上,这意味着比寄存器太大的任何东西都将通过引用传递.但这是一个实现细节,是编译器的业务,而不是你的业务.你甚至不应该考虑它,除非在极少数情况下.
所以咬紧牙关并将裸露的阵列作为in out参数传递.相信我,你会喜欢它.
type vector is array (natural range <>) of integer;
my_vec : vector(1..3);
procedure test (subject : in out vector) is
begin
...
end;
Run Code Online (Sandbox Code Playgroud)
Ada被设计成几乎在所有情况下都可以使用,而不需要指针,并且可以在除极少数非常罕见的情况下使用而无需指向堆栈分配对象的指针.
前者相当不安全(来自未分配指针和内存泄漏的危险),后者更不安全(堆栈对象可能在指针执行之前超出范围,即使它们没有一个小尺寸错误也会破坏整个程序).你仍然可以在Ada中做到这两点,但与许多语言不同,它的目的是让不安全的东西需要你做更多的工作,并使非常不安全的东西成为一个主要的PITA写.
例如,如果您只是动态分配整个数组,那么您就不必为此aliased和all业务而愚弄.此外,如果您只想将数组传递给子例程,您可以简单地将其作为参数传递,您甚至不必愚弄动态分配和解除分配.同样,Ada编译器足够聪明,可以通过引用传递大对象(是的,即使您指定了in).这需要从C/C++编码器调整态度,他们习惯于告诉他们的dumbass编译器不要在堆栈上传递10meg对象.你必须学会让Ada编译器担心如何有效地传递你的参数,你可以担心如何编写出色的代码.