comp.lang.ada
 help / color / mirror / Atom feed
* Re: Array access via pointer?
  2000-08-01  0:00 Array access via pointer? Michael Carman
@ 2000-08-01  0:00 ` Ted Dennison
  2000-08-02  0:00   ` Michael Carman
  2000-08-02  0:00 ` Markku Kotiaho
  2000-08-02  0:00 ` tmoran
  2 siblings, 1 reply; 12+ messages in thread
From: Ted Dennison @ 2000-08-01  0:00 UTC (permalink / raw)


In article <398721AD.CAEE3A51@home.com>,
  Michael Carman <mjcarman@home.com> wrote:

> type Addr_Table is array (Natural range <>) of System.Address;
>
> Arr1 : Addr_Table (0 .. 100);
> Arr2 : Addr_Table (0 .. 20);
>
> procedure Foo (Addr : in System.Address;
>                I    : in Integer) is
> begin
>     -- Do something with index I of the array at Addr
> end Foo;

> fight against the language. So, what's the canonical way of doing
> this in Ada?

That would be:

procedure Foo (Addr : in out Addr_Table;
               I    : in     Integer) is
begin
   -- Do something with index I of the array at Addr
end Foo;

It may be much more constructive for you to tell us why you feel you
need to use addresses and pointers. In Ada you almost *never* have to
use addresses, and rarely have to use pointers. Unless you have an
actual dynamic or linked data structure, or are interfacing to some
external C or OS call, you are probably doing something wrong when you
write code with addresses and/or pointers in it.

--
T.E.D.

http://www.telepath.com/~dennison/Ted/TED.html


Sent via Deja.com http://www.deja.com/
Before you buy.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Array access via pointer?
@ 2000-08-01  0:00 Michael Carman
  2000-08-01  0:00 ` Ted Dennison
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Michael Carman @ 2000-08-01  0:00 UTC (permalink / raw)


First, a warning: my knowledge of Ada is pretty rudimentary, and I tend
to use the terms I'm familiar with from other languages. If words like
"pointer" and "reference" betray that background, oh well.

Quick overview:
I have several arrays, each holding the same type of data (system 
addresses) but the arrays are of different sizes. I want to have a 
single procedure to process the data in these arrays. (For various 
reasons, the numbers/sizes of arrays are necessary, so no paradigm 
shifts allowed there!) In order to do this I pass my procedure a
pointer to an array and an index into it. It looks something like
this:

type Addr_Table is array (Natural range <>) of System.Address;

Arr1 : Addr_Table (0 .. 100);
Arr2 : Addr_Table (0 .. 20);

procedure Foo (Addr : in System.Address;
               I    : in Integer) is
begin
    -- Do something with index I of the array at Addr
end Foo;

A call to it might look like Foo (Arr2'Address, 7). Inside Foo, I tried 
to get at the array data in this manner:

    Data := Addr_To_Ptr(Addr).all (Idx);

where 

    type Addr_Table_Ptr is access Addr_Table;
    function Addr_To_Ptr is new Unchecked_Conversion
        (System.Address, Addr_Table_Ptr);

but that gave me a constraint error, apparently because type Addr_Table 
is unconstrained and the instantiaions of it are not. Yes, if Addr_Table
had a definate size this would be easy, but it doesn't and (for me) it's
not.

The only way I've been able to make it work is with this:

    Data := Addr_To_Ptr(Addr + Idx * Size_In_Words).all;

where

    type Addr_Ptr is access System.Address;
    function Addr_To_Ptr is new Unchecked_Conversion
        (System.Address, Addr_Ptr);
    Size_In_Words := System.Word_Size / System.Storage_Unit;

but that seems unnecessarily messy. Well, it looks like C, which 
wouldn't really bother me but I'm not writing C at the moment. It 
seems to me that there should be a way to do this without having to 
fight against the language. So, what's the canonical way of doing 
this in Ada?

-mjc




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-01  0:00 Array access via pointer? Michael Carman
  2000-08-01  0:00 ` Ted Dennison
  2000-08-02  0:00 ` Markku Kotiaho
@ 2000-08-02  0:00 ` tmoran
  2000-08-02  0:00   ` Michael Carman
  2 siblings, 1 reply; 12+ messages in thread
From: tmoran @ 2000-08-02  0:00 UTC (permalink / raw)


Arr2'Address is the address of Arr2(0).  You are trying to convert
that to an access value, and not even an access to Arr2(0), but an
access to Arr2, which isn't the same thing.  So with your unchecked
conversion, you are telling the compiler that a pointer to an
element of Arr2, ie a pointer to a System.Address, is a pointer
to an Addr_Table, an array.  Since Addr_Table is unconstrained,
the compiler must store the actual bounds somewhere, so it probably
thinks your pointer points to a bounds dope vector stored at the
beginning of Arr2, when in fact it points to some System.Address value.

>A call to it might look like Foo (Arr2'Address, 7). Inside Foo, I tried
>to get at the array data in this manner:
>
>    Data := Addr_To_Ptr(Addr).all (Idx);
>where
>
>    type Addr_Table_Ptr is access Addr_Table;
>    function Addr_To_Ptr is new Unchecked_Conversion
>        (System.Address, Addr_Table_Ptr);
  An Address and an access type are not the same thing, so you are
crossing your fingers and guessing when you use Unchecked_Conversion.
Use instead predefined package System.Address_To_Access_Conversions.
(But don't try to claim a System.Address is an Addr_Table.)

>procedure Foo (Addr : in System.Address;
>               I    : in Integer) is
>begin
>    -- Do something with index I of the array at Addr
>end Foo;

   Why not

procedure Foo (Addr : in out Addr_Table;  -- both read&write access
               I    : in     Integer) is
begin
    -- Do something with index I of the array at Addr, ie, Addr(I)
end Foo;

  called with

Foo(Arr2, 7);

   or

procedure Foo (Addr : in out System.Address) is
begin
    -- Do something with Addr
end Foo;

   called with

Foo(Arr2(7));




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-01  0:00 ` Ted Dennison
@ 2000-08-02  0:00   ` Michael Carman
  2000-08-03  0:00     ` Ken Garlington
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Carman @ 2000-08-02  0:00 UTC (permalink / raw)


Ted Dennison wrote:
> 
> procedure Foo (Addr : in out Addr_Table;
>                I    : in     Integer) is
> begin
>    -- Do something with index I of the array at Addr
> end Foo;

Yes, that's much cleaner, thank you. Is it safe to assume that
internally Addr_Table is passed by reference? (It's a bit more data than
I want on the stack.)

> It may be much more constructive for you to tell us why you feel you
> need to use addresses and pointers. 
> [...]

Which pointers -- the ones to my arrays or the ones inside them? :) I
assure you that the latter are necessary; they tell me where to find
data from an external process. I'd happily get rid of the former ones,
though.

My example was simplified to illustrate the problem I was having.
Unfortunately, it oversimplified the situation a bit. I wasn't passing
in a pointer to an array just for fun. I determine which array to
process in a completely seperate part of the program. That is, I don't
actually call Foo() this way:

    Foo(Arr2'Address, 7);

I have some higher-up logic that's something like this:

if (<condition>) then
    Arr_Ptr := Arr1'Address;
else
    Arr_Ptr := Arr2'Address;
end if;

Deeper down, in a completely seperate part of things, I call

    Foo(Arr_Ptr, 7);

So the later code is fat, dumb and happy, knowing nothing about the
earlier logic. Your example passing Addr_Table instead of a pointer is
great, but I need to keep this functionality. Is there a way to alias
variables such that I can set "My_Array := Arr2" (without actually
creating a copy)? All I've been able to find is defining aliased
variables, and then using access types to get to them, which puts me
back in the pointer/dereference boat.

[To further complicate things, I can't use 'Access -- I'm trying to keep
my code Ada83 compatible -- I know how to work around it, it's just
messier.]

Of course, that's still better than what I'm currently doing.

-mjc




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-02  0:00 ` tmoran
@ 2000-08-02  0:00   ` Michael Carman
  2000-08-02  0:00     ` tmoran
  0 siblings, 1 reply; 12+ messages in thread
From: Michael Carman @ 2000-08-02  0:00 UTC (permalink / raw)


tmoran@bix.com wrote:
> 
> Arr2'Address is the address of Arr2(0).  You are trying to convert
> that to an access value, and not even an access to Arr2(0), but an
> access to Arr2, which isn't the same thing.  So with your unchecked
> conversion, you are telling the compiler that a pointer to an
> element of Arr2, ie a pointer to a System.Address, is a pointer
> to an Addr_Table, an array.  Since Addr_Table is unconstrained,
> the compiler must store the actual bounds somewhere, so it probably
> thinks your pointer points to a bounds dope vector stored at the
> beginning of Arr2, when in fact it points to some System.Address value.

But shouldn't Ada know that if I say Arr2'Address I want a pointer to
the array, not it's first element? Either way, I agree that it's a mess,
which I why I came here appealing for help!
 
>   An Address and an access type are not the same thing, so you are
> crossing your fingers and guessing when you use Unchecked_Conversion.
> Use instead predefined package System.Address_To_Access_Conversions.

Well, no, I wasn't just taking a wild guess. The size and value of the
two types are the same; it's just how Ada thinks of them that's
different. Just for my own sanity, I looked at the body for
System.Address_To_Access_Conversions. To_Pointer() and To_Address() 
are just Unchecked_Conversions (though dressed up a bit with private
types). I thank you though, because using that package will prevent me
from having to declare a bunch of these things myself.

-mjc




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-02  0:00   ` Michael Carman
@ 2000-08-02  0:00     ` tmoran
  0 siblings, 0 replies; 12+ messages in thread
From: tmoran @ 2000-08-02  0:00 UTC (permalink / raw)


>The size and value of the two types [System.Address, Arr2'access]
>are the same; it's just how Ada thinks of them that's
>different. Just for my own sanity, I looked at the body for
>System.Address_To_Access_Conversions. To_Pointer() and To_Address()
>are just Unchecked_Conversions (though dressed up a bit with private
  Perhaps on the compiler and OS and machine you are using, they happen
to be the same.  On a compiler I regularly use that is targeted at
Intel chips, 'access is 32 bits (assume a single segment, ie flat
memory model), but System.Address is 48 bits (segment + offset,
necessary in some situations) Clearly you can't use
Unchecked_Conversion there, and the compiler's
System.Address_To_Access_Conversions takes account of the difference.

>Well, no, I wasn't just taking a wild guess.
  Just making an unjustified assumption. ;)




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-01  0:00 Array access via pointer? Michael Carman
  2000-08-01  0:00 ` Ted Dennison
@ 2000-08-02  0:00 ` Markku Kotiaho
  2000-08-02  0:00 ` tmoran
  2 siblings, 0 replies; 12+ messages in thread
From: Markku Kotiaho @ 2000-08-02  0:00 UTC (permalink / raw)




Michael Carman wrote:

> ...:
>
> type Addr_Table is array (Natural range <>) of System.Address;
>
> Arr1 : Addr_Table (0 .. 100);
> Arr2 : Addr_Table (0 .. 20);
>
> procedure Foo (Addr : in System.Address;
>                I    : in Integer) is
> begin
>     -- Do something with index I of the array at Addr
> end Foo;

You could just change Foo to something like:
procedure Foo (Addr_Table_Entry : in System.Address);

And call it with something like:
Foo(Arr2(7));

Inside Foo, you can get at the array element which you sent with:
Data := Addr_Table_Entry;

> .... It
> seems to me that there should be a way to do this without having to
> fight against the language. So, what's the canonical way of doing
> this in Ada?
>
> -mjc

This may not be the "canonical way," but that would probably require
rethinking your design entirely.

MK






^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-02  0:00   ` Michael Carman
@ 2000-08-03  0:00     ` Ken Garlington
  2000-08-03  0:00       ` Robert A Duff
  0 siblings, 1 reply; 12+ messages in thread
From: Ken Garlington @ 2000-08-03  0:00 UTC (permalink / raw)


"Michael Carman" <mjcarman@home.com> wrote in message
news:3988269B.D1DB4EA5@home.com...

[snip]

> My example was simplified to illustrate the problem I was having.
> Unfortunately, it oversimplified the situation a bit. I wasn't passing
> in a pointer to an array just for fun. I determine which array to
> process in a completely seperate part of the program.

[snip]

> [To further complicate things, I can't use 'Access -- I'm trying to keep
> my code Ada83 compatible -- I know how to work around it, it's just
> messier.]

Well, the Ada95 approach using 'Access is certainly much easier, but if you
have to stick with Ada83, IIRC we had some luck with the following:

---
with System, Unchecked_Conversion;
package Address_Fun is

  type Addr_Table_Values is array (Natural range <>) of System.Address;

 -- First, Last can be changed to Length if desired
  type Addr_Table (First, Last: Natural) is record
     Values: Addr_Table_Values(First .. Last);
  end record;

  type Addr_Table_Access is access Addr_Table;

  function To_Addr_Table_Access is new Unchecked_Conversion (System.Address,
Addr_Table_Access);

  procedure Foo (Table: in Addr_Table_Access; I: in Integer);

end Address_Fun;






^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-03  0:00     ` Ken Garlington
@ 2000-08-03  0:00       ` Robert A Duff
  2000-08-03  0:00         ` Ken Garlington
  0 siblings, 1 reply; 12+ messages in thread
From: Robert A Duff @ 2000-08-03  0:00 UTC (permalink / raw)


"Ken Garlington" <Ken.Garlington@computer.org> writes:

> "Michael Carman" <mjcarman@home.com> wrote in message
> news:3988269B.D1DB4EA5@home.com...
...
> > [To further complicate things, I can't use 'Access -- I'm trying to keep
> > my code Ada83 compatible -- I know how to work around it, it's just
> > messier.]

If you want to pass a pointer to an array, pass an access value, not an
address.  If you're stuck with Ada 83, then you will have to allocate
the arrays in the heap, using 'new'.

- Bob




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-03  0:00       ` Robert A Duff
@ 2000-08-03  0:00         ` Ken Garlington
  2000-08-04  0:00           ` Robert I. Eachus
  0 siblings, 1 reply; 12+ messages in thread
From: Ken Garlington @ 2000-08-03  0:00 UTC (permalink / raw)



"Robert A Duff" <bobduff@world.std.com> wrote in message
news:wcc66pi304z.fsf@world.std.com...
> "Ken Garlington" <Ken.Garlington@computer.org> writes:
>
> > "Michael Carman" <mjcarman@home.com> wrote in message
> > news:3988269B.D1DB4EA5@home.com...
> ...
> > > [To further complicate things, I can't use 'Access -- I'm trying to
keep
> > > my code Ada83 compatible -- I know how to work around it, it's just
> > > messier.]
>
> If you want to pass a pointer to an array, pass an access value, not an
> address.  If you're stuck with Ada 83, then you will have to allocate
> the arrays in the heap, using 'new'.

No, you don't have to allocate the arrays in the heap -- so long as you're
willing to accept the risks of converting a System.Address to an access
type! (For the specific example I gave, the risks appear to be low in my
experience.)






^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-03  0:00         ` Ken Garlington
@ 2000-08-04  0:00           ` Robert I. Eachus
  2000-08-04  0:00             ` Ken Garlington
  0 siblings, 1 reply; 12+ messages in thread
From: Robert I. Eachus @ 2000-08-04  0:00 UTC (permalink / raw)


Ken Garlington wrote:
 
> No, you don't have to allocate the arrays in the heap -- so long as you're
> willing to accept the risks of converting a System.Address to an access
> type! (For the specific example I gave, the risks appear to be low in my
> experience.)

   And my experience has been quite the opposite!  If your only use of
the 'trick' is to convert the address of an object to an access value
designating the object, it will usually work.  In general in Ada 95 the
address of an array object should be the address of the first element:

   "For an array X, X'Address should point at the first component of the
array,
and not at the array bounds."  RM 13.3(14)

   The first thing to note about the paragraph quoted above is that this
is in a section titled, "Implementation Advice."  Of course, most
compilers do follow this advice.  However, if you pass in the address of
a component of the array, other than the first, things will often go
wrong.  Some compilers implement the above advice by storing any
necessary descriptor data at a negative offset from the address, which
is probably deadly in the case under discussion.  Other compilers do
this by materializing the descriptor data where necessary and, if
necessary  by passing additional 'hidden' parameters as part of calls
with parameters of the array base type, whether or not the parameter
subtype is actually constrained.  In this case, if you don't materialize
the data in an Ada array, the compiler has no place to go to find the
attributes it needs to create the call. Often this means that you need
an object, sometimes a constant object, which has the correct
attributes.  You then can use an attribute definition clause to say that
the object is located at the address of the actual data.  Remember that
in Ada you can have a nested declare block--or even a procedure or
function--that declares both the subtype bounds and the address
differently each time it is entered:

    procedure Map_Array(Addr: in System.Address; First, Last: in
Integer) is
      Temp: My_Array_Type(First..Last);
      for Temp'Address use Addr;
    begin
      Some_Stuff;
      -- in here it is safe to treat the data as an Ada array,
      -- assuming all the parameters are correct.
    end Map_Array;

    You can even make Map_Array a generic procedure with a subprogram
parameter,
and use it to apply different actions to the array.  Sound complex? 
Actually this approach to interfacing to hardware or other programming
languages can get much hairier.  If you are interfacing to actual
hardware registers or to code running in another thread, you may also
need to specify pragmas Atomic, Atomic_Components, Volatile or
Volatile_Components.  Figuring out which you may need is a non-trivial
exercise, and is common to all interfaces no matter how they are
declared.

   The right solution, at least to the interfacing problems is to use
Annex B.  After all that is what it is there for.  In this particular
example, the package Interfaces.C.Pointers may be just what the doctor
ordered.  Again, though, if you are interfacing to hardware or to
another thread or process, watch it.  It is up to you to warn the Ada
compiler what the other guy is doing using the above pragmas.




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Array access via pointer?
  2000-08-04  0:00           ` Robert I. Eachus
@ 2000-08-04  0:00             ` Ken Garlington
  0 siblings, 0 replies; 12+ messages in thread
From: Ken Garlington @ 2000-08-04  0:00 UTC (permalink / raw)



"Robert I. Eachus" <rieachus@earthlink.net> wrote in message
news:398A1B77.A2A3D302@earthlink.net...
> Ken Garlington wrote:
>
> > No, you don't have to allocate the arrays in the heap -- so long as
you're
> > willing to accept the risks of converting a System.Address to an access
> > type! (For the specific example I gave, the risks appear to be low in my
> > experience.)
>
>    And my experience has been quite the opposite!  If your only use of
> the 'trick' is to convert the address of an object to an access value
> designating the object, it will usually work.  In general in Ada 95 the
> address of an array object should be the address of the first element:
>
>    "For an array X, X'Address should point at the first component of the
> array,
> and not at the array bounds."  RM 13.3(14)

Look at the code I posted. It doesn't take the address of an array.

>    The right solution, at least to the interfacing problems is to use
> Annex B.

Unfortunately, the problem is constrained to Ada83, so that's not much help.
The solution *as posted* works on a variety of compilers.






^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2000-08-04  0:00 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-08-01  0:00 Array access via pointer? Michael Carman
2000-08-01  0:00 ` Ted Dennison
2000-08-02  0:00   ` Michael Carman
2000-08-03  0:00     ` Ken Garlington
2000-08-03  0:00       ` Robert A Duff
2000-08-03  0:00         ` Ken Garlington
2000-08-04  0:00           ` Robert I. Eachus
2000-08-04  0:00             ` Ken Garlington
2000-08-02  0:00 ` Markku Kotiaho
2000-08-02  0:00 ` tmoran
2000-08-02  0:00   ` Michael Carman
2000-08-02  0:00     ` tmoran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox