* 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 ` Michael Carman 2000-08-02 0:00 ` tmoran 2000-08-02 0:00 ` Markku Kotiaho 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
* 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 ` 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
* 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 ` tmoran 2000-08-02 0:00 ` Michael Carman 2000-08-02 0:00 ` Markku Kotiaho 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-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 ` tmoran @ 2000-08-02 0:00 ` Markku Kotiaho 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
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 ` tmoran 2000-08-02 0:00 ` Michael Carman 2000-08-02 0:00 ` tmoran 2000-08-02 0:00 ` Markku Kotiaho
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox