从 System.Address 转换为 Ada 中的整数

Convert from System.Address to Integer in Ada

在下面的例子中,我想知道,为什么line 17不行,而line 18呢?我不能将 System.Address 直接转换为 Integer(参见 line 17)吗?

main.adb

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

procedure Main is
   package SSE renames System.Storage_Elements;

   type Integer_Access is access Integer;
   I1_Access : Integer_Access := new Integer'(42);
   I1_Address : System.Address := I1_Access.all'Address;

   function Convert1 is new Ada.Unchecked_Conversion (System.Address, Integer);
   function Convert2 is new Ada.Unchecked_Conversion (System.Address, Integer_Access);
begin
   Ada.Text_IO.Put_Line (SSE.To_Integer (I1_Access'Address)'Img);
   Ada.Text_IO.Put_Line (SSE.To_Integer (I1_Access.all'Address)'Img);
   Ada.Text_IO.Put_Line (I1_Access.all'Img);
   Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img);  --  why does this NOT work?
   Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img);  --  why does this work?
end Main;

结果

 140734773254664
 140243203260416
 42
-363855872
 42

确实有效。显然它正在做一些与您预期不同的事情。

您可以使用 Unchecked_ConversionSystem.Address 转换为 Integer,但结果不一定有意义。您将得到一个整数,表示 System.Address 值中保存的(可能是虚拟的)地址—— 而不是 它指向的任何对象的值。如果 System.AddressInteger 大小不同,结果将更没有意义。

Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img);

这会打印内存地址的 Integer 表示。意义不是特别大。 (通常您希望看到这样的十六进制地址。)

Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img);

这会在 I1_Address 的值指示的内存位置打印对象的 Integer42。这只是打印 I1_Access.all.

的一种迂回方式

如果我使用 -gnatwa(大多数警告)和 -gnatl(生成列表)在此 Mac 上编译您的代码,我得到(摘录)

12.    function Convert1 is new Ada.Unchecked_Conversion (System.Address, Integer);
       |
    >>> warning: types for unchecked conversion have different sizes

因为 Integer 是 32 位,而 System.Address(和大多数访问类型)是 64 位。你的机器显然是相似的。

所以你得到奇怪的第 5 行输出的原因(顺便说一句,我得到了 -490720512)是因为它只查看实际地址的底部 32 位。

您可以查看 System.Address_To_Access_Conversions (ARM 13.7.2) 以了解支持的方法。

如果您只想打印图像的值,如您的示例所示,请考虑使用函数 System.Address_Image。这对指针运算不利,但会导致更好的输出(例如十六进制)