可以修改通过“地址”属性传递给过程的变量吗?

Can a variable passed with 'address attribute to a procedure be modified?

在我下面的测试代码中,我试图通过将变量作为 system.address 传递给另一个过程来修改它。

with Ada.Text_IO;
with System;
with System.Storage_Elements;


procedure Main is
  
  procedure Modify ( Var : in out System.Address) is
    use System.Storage_Elements;
  begin
    Var := Var + 10;
  end Modify;
  
  My_Var : Integer := 10; 
begin
  --  Insert code here.
  Modify (My_Var'Address);
  Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image ); 
  
end Main;

编译器返回如下错误,

17:17 actual for "Var" must be a variable

我无法理解原因,因为 My_Var(Var 的实际值)显然是一个变量。我应该更改什么以将 My_Var 修改为 system.address?

注意:这条线索的上下文是我试图理解现有遗留项目中的接口模块。虽然可能有更好的方法来实现我的需要,但我想了解是否可以使用上述方法修改变量。

你修改的是地址,不是变量。尝试将参数更改为 Addr : in System.Address 并在 Modify.

中声明 Var : Integer with Address => Addr

如果您能展示遗留界面模块的相关部分,将会很有帮助 -- 这将有助于我们了解您的需要和想要做的事情。

也就是说,首先请注意,在 Ada 中通常不会通过显式传递“实际变量的地址”来通过引用传递参数。正如您所说,还有其他更好的方法。

如果你传递一个 System.Address 值,然后想要读取或写入驻留在该地址的任何数据,你必须通过你强制拥有该地址的变量来执行 read/write ,或通过您强制指向该寻址位置的访问值(Ada 等效的“指针”)。在这两种情况下,您都有责任确保变量或访问值的类型与您要读取或写入的数据的实际类型匹配。

要创建指向给定地址内存的访问值,您应该使用预定义包 System.Address_To_Access_Conversions。这需要对访问值和泛型有一定的了解,所以我不会在这里展示示例。

要强制变量具有给定地址,您声明变量时将地址方面设置为给定地址。下面的代码显示了如何为此示例完成此操作。注意局部变量的声明Modify.Var(注意我把参数的名字从Var改成了Var_Addr)。

with Ada.Text_IO;
with System;

procedure Mod_By_Addr is

  procedure Modify (Var_Addr : in System.Address) is
    Var : Integer with Address => Var_Addr;
  begin
    Var := Var + 10;
  end Modify;

  My_Var : aliased Integer := 10;

begin
  Modify (My_Var'Address);
  Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image );

end Mod_By_Addr;

由于Var_Addr参数在Modify过程中没有被修改,所以可以用in方式声明,所以实参可以是表达式(My_Var'Address) .

HTH

另一种修改变量的方法我已经理解使用address_to_Access_Conversions如下所示,

with Ada.Text_IO;
with System.Address_To_Access_Conversions;
with System.Storage_Elements;

procedure Main is

  procedure Modify ( Var : in System.Address) is
    use System.Storage_Elements;
    package Convert is new System.Address_To_Access_Conversions (Integer);
  begin
    Ada.Text_IO.Put_Line(Convert.To_Pointer (Var).all'Img);
  end Modify;

  My_Var : Integer := 10;
begin
  Modify (My_Var'Address);
  Ada.Text_IO.Put_Line("My_Var is:" & Integer(My_Var)'Image );

end Main;