从 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_Conversion
将 System.Address
转换为 Integer
,但结果不一定有意义。您将得到一个整数,表示 System.Address
值中保存的(可能是虚拟的)地址—— 而不是 它指向的任何对象的值。如果 System.Address
和 Integer
大小不同,结果将更没有意义。
Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img);
这会打印内存地址的 Integer
表示。意义不是特别大。 (通常您希望看到这样的十六进制地址。)
Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img);
这会在 I1_Address
的值指示的内存位置打印对象的 Integer
值 42
。这只是打印 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
。这对指针运算不利,但会导致更好的输出(例如十六进制)
在下面的例子中,我想知道,为什么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_Conversion
将 System.Address
转换为 Integer
,但结果不一定有意义。您将得到一个整数,表示 System.Address
值中保存的(可能是虚拟的)地址—— 而不是 它指向的任何对象的值。如果 System.Address
和 Integer
大小不同,结果将更没有意义。
Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img);
这会打印内存地址的 Integer
表示。意义不是特别大。 (通常您希望看到这样的十六进制地址。)
Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img);
这会在 I1_Address
的值指示的内存位置打印对象的 Integer
值 42
。这只是打印 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
。这对指针运算不利,但会导致更好的输出(例如十六进制)