Ada数组访问:指向数组中特定项的指针,该位置基于输入参数是动态的。

时间:2010-09-23 17:25:38

标签: pointers ada

我在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;

这对指针定义的编译失败,说

  

“'ACCESS的前缀必须是对象的别名视图或表示具有非内在调用约定的子程序”

如果我然后将矢量本身的定义更改为:

my_vec : aliased vector  

它现在返回编译器错误:

  

“X'ACCESS的预期类型,其中X表示对象的别名视图,必须是一般访问类型”

在一天结束时,我真正需要的是指向数组中特定项的指针,该位置基于输入参数是动态的。有人能指出我正确的方向吗?

3 个答案:

答案 0 :(得分:6)

如果您正在使用GNAT,那么“必须是一般访问类型”之后的错误消息应该为您提供了解决方案:

  

添加“all”以输入“vector_access”   在行...中定义。

这样你最终会得到:

type Vector_Access is access all Vector;

使用“all”来指定一般访问类型与Ada中的动态内存分配池有关。如果您不关心动态内存分配池,那么不要担心它,只需在访问类型定义中包含“all”。

我不确定这是否是你在一天结束时所寻找的内容的一部分,但是你知道在大多数情况下Ada的访问(指针)类型用于处理动态分配的内存,对吧?

因此,不是将my_vec指向别名变量,而是动态分配它:

Pointer_2_Dynamic : vector_access := new Vector;

通过这种方式,您可以在运行时动态分配所需的对象,并轻松处理可变大小的对象(尽管您需要使用不同的向量定义来实现此目的:

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);

答案 1 :(得分:5)

行。专家Cish编码员在Ada上的第一课: Ada参数与Cish参数不同。在C中,(预引用参数)每个参数都相当于一个Ada'in'参数,附加条件是C编译器必须总是愚蠢地传递堆栈中的整个内容,无论它有多大。因此,你可怜的C编码器将它钉入你的大脑,你永远不会将大型对象直接传递给子程序,但总是使用指针。

Ada与众不同。您告诉编译器您希望如何访问参数(只读 - '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; 

Ada被设计成几乎在所有情况下都可以使用而不需要指针,并且可以在除极少数非常罕见的情况下使用而无需指向堆栈分配对象的指针。

前者相当不安全(来自未分配指针和内存泄漏的危险),后者更不安全(堆栈对象可能在指针执行之前超出范围,即使它们没有一个小尺寸错误也可以腐蚀整个程序)。你仍然可以在Ada中做到这两点,但与许多语言不同的是,它设计用于使不安全的事情需要你做更多的工作,并使非常不安全的东西成为PITA的主要写作。

例如,如果您只是动态分配整个数组,则不必愚弄这个aliasedall业务。此外,如果您只想将数组传递给子例程,您可以简单地将其作为参数传递,您甚至不必愚弄动态分配和解除分配。同样,Ada编译器足够聪明,可以通过引用传递大对象(是的,即使您指定了in)。这需要从C / C ++编码器调整态度,他们习惯于告诉他们的dumbass编译器不要在栈上传递10meg对象。你必须学会​​让Ada编译器担心如何有效地传递你的参数,你可以担心如何编写出色的代码。

答案 2 :(得分:1)

想想我发现它,对于遇到同样问题的其他人来说。

答案与特定的别名有关。数组声明需要是:

type vector is array (1 .. 3) of aliased integer;

为了确保整数存储在内存中,而不是寄存器。