ada - 可以修改通过 'address 属性传递给过程的变量吗?

标签 ada memory-address gnat

在下面的测试代码中,我尝试通过将变量作为 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 的实际值) 显然是一个变量。我应该更改什么来使用 system.address 修改 My_Var?

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

最佳答案

如果您能够展示旧界面模块的相关部分,将会很有帮助——这将帮助我们了解您需要什么和想要做什么。

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

如果您传递 System.Address 值,然后想要读取或写入该地址上驻留的任何数据,则必须通过强制拥有该地址的变量或通过访问值来执行读/写操作(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

关于ada - 可以修改通过 'address 属性传递给过程的变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68591568/

相关文章:

Ada 中断处理程序

c++ - 内存寻址与数组的混淆

generics - 有没有办法在 Ada(特别是 GNAT)中创建和重用方面集?

c++ - 如何将退出代码从 Ada 进程返回到调用 Windows 进程?

ada - "no selector"是什么意思?

c - 在C中的地址位置存储一个字符

ada - 将结构/记录从汇编器传递到 Ada

command-line-arguments - GNAT.Command_Line 中的选项参数存在问题

Ada:组件与父级重叠的派生记录

c - 为什么两个变量共享同一个地址?