user1091344
user1091344

Reputation: 740

Convert from System.Address to Integer in Ada

In the example below, I am wondering, why line 17 does not work, but line 18? Can I not convert a System.Address directly to an Integer (see 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;

Result

 140734773254664
 140243203260416
 42
-363855872
 42

Upvotes: 3

Views: 6156

Answers (3)

manuBriot
manuBriot

Reputation: 2715

If you only want to print the value of an image, as in your example, consider using the function System.Address_Image. This is not good for pointer arithmetic, but leads to better output (hexadecimal, for instance)

Upvotes: 4

Simon Wright
Simon Wright

Reputation: 25501

If I compile your code on this Mac with -gnatwa (most warnings) and -gnatl (generate a listing) I get (excerpted)

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

because Integer is 32-bits while System.Address (and most access types) are 64-bits. Your machine is evidently similar.

So the reason you get a weird 5th output line (I got -490720512, by the way) is that it’s only looking at the bottom 32 bits of the actual address.

You might look at System.Address_To_Access_Conversions (ARM 13.7.2) for the supported way to do this.

Upvotes: 6

Keith Thompson
Keith Thompson

Reputation: 263287

It does work. Apparently it's doing something other than what you expected.

You can convert a System.Address to an Integer using Unchecked_Conversion, but the result isn't necessarily going to be meaningful. You'll get an integer representing the (probably virtual) address held in the System.Address value -- not the value of whatever object it points to. And if System.Address and Integer aren't the same size, the result will be even less meaningful.

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

This prints an Integer representation of a memory address. It's not particularly meaningful. (Typically you'd want to see such an address in hexadecimal.)

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

This prints the Integer value, 42, of the object at the memory location indicated by the value of I1_Address. It's just a roundabout way of printing I1_Access.all.

Upvotes: 4

Related Questions