From: Craig Carey <research@ijs.co.nz>
Subject: Re: Representing data differently
Date: Sun, 09 Feb 2003 17:39:21 +1300
Date: 2003-02-09T17:39:21+13:00 [thread overview]
Message-ID: <c5cb4v03pves595pdtq3euo1glgf5ne71q@4ax.com> (raw)
In-Reply-To: GBS0a.26741$HN5.82176@rwcrnsc51.ops.asp.att.net
On Fri, 07 Feb 2003 18:07:34 GMT, tmoran@acm.org wrote:
>>In C I can represent the same data multiple ways using structs and
>>unions. How and can I do this in Ada?
>
> In Ada it's called Unchecked_Conversion. It's "unchecked" because
>there's not much the compiler can do to help check that you coded
>what you meant to code. Look it up in any Ada text.
This message provides a more details and it has an example showing how
to make two records be of the same size.
Suppose that there is a generic package that has to be instantiated
only once (otherwise, with GNAT, the executables get larger), but the
instantiated generic package has receive two completely different
types.
The generic package has this header:
generic
type Data_Type is private; -- Constrained only
...
The package passes these 3 checks:
* The 'union' type is not a pointer to both records. In this option
and unchecked conversion would be done on the pointers. It is
simple to specify but leads to harder to write code and probably
a larger executable.
* The 'union' type is not a variant, and it is not a tagged type.
Those two types are unconstrained.
--------------------------------------------------------------------
with Ada.Unchecked_Conversion;
package Bt is
type Kind_Enum is (Kind_R1, Kind_R2, Kind_Zero);
-- Help catch unitialized value bugs in Linux:
for Kind_Enum use (Kind_R1 => 7, Kind_R2 => 8, Kind_Zero => 9);
pragma Volatile (Kind_Enum); -- Inlined code uses field's value
type Hoof_Rec is null record;
type R1_Rec is
record
X1 : Integer;
end record;
type R2_Rec is
record
Y1 : String (1 .. 7);
Y2 : Boolean;
end record;
for Hoof_Rec'Alignment use 4;
for R1_Rec'Alignment use 4;
for R2_Rec'Alignment use 4;
Size : constant := 64; -- Adjust by hand
for Hoof_Rec'Size use Size;
for R1_Rec'Size use Size;
for R2_Rec'Size use Size;
type Variant is
record
Kind : Kind_Enum := Kind_Zero;
K : Hoof_Rec;
end record;
function From_R1 (X : R1_Rec) return Variant;
function To_R1 is new Ada.Unchecked_Conversion (
Source => Hoof_Rec, Target => R1_Rec);
private
function From_R1 is new Ada.Unchecked_Conversion (
Source => R1_Rec, Target => Hoof_Rec);
end Bt;
--------------------------------------------------------------------
with Text_IO;
package body Bt is
function From_R1 (X : R1_Rec) return Variant is
begin
return (Kind => Kind_R1, K => From_R1 (X));
end From_R1;
begin
declare
Z0 : Hoof_Rec;
Z1 : R1_Rec;
Z2 : R2_Rec;
function Nim (Omicron : Natural) return String
renames Natural'Image;
function From_R1_To_R2 is new Ada.Unchecked_Conversion (
Source => R1_Rec, Target => R2_Rec);
begin
-- Prints "64 64 64 TRUE":
Text_IO.Put_Line (Nim (Z0'Size) & Nim (Z1'Size) &
Nim (Z2'Size) & ' ' &
Boolean'Image (From_R1_To_R2 (Z1).Y2));
-- In GNAT,T'Object_Size to get the size of the variables
-- without defining variables.
if Z0'Size /= Z1'Size or Z0'Size /= Z2'Size then
raise Program_Error;
end if;
end;
end Bt;
--------------------------------------------------------------------
pragma Style_Checks ("3abcefhiklmnoprst");
with Bt;
procedure Bt_Main is
begin
null;
end Bt_Main;
--------------------------------------------------------------------
The text
"From_R1_To_R2 (Z1).Y2"
shows a way to use Unchecked_Conversion that permits the compiler to
not copy the entire record. That is permitted by AARM 13.9
(Unchecked Type Conversions), which says:
12 An implementation may return the result of an unchecked
conversion by reference, if the Source type is not a by-copy type.
[In this case, the result of the unchecked conversion represents
simply a different (read-only) view of the operand of the
conversion.]
12.a Ramification: In other words, the result object of a call on an
instance of Unchecked_Conversion can occupy the same storage as the
formal parameter S.
For GNAT, adding a ".all" and having the conversion be applying to
a pointer to a record easily could reduce the chance of copying.
--
For completeness, the Unchecked_Conversion feature and its copying, can
be avoided, by using this technique:
for X'Address use Y'Address;
pragma Import (Y);
-- :Stops default initialising of pointers (not in GNAT 3.14)
If X or Y is an "in out" mode record parameter then it could be copied
in or out. Making it tagged guarantees that that doesn't happen.
AARM 3.10 (Access Types) says:
(9.g) A formal parameter of a tagged type is defined to be aliased so
that a (tagged) parameter X may be passed to an access parameter P by
using P => X'Access. Access parameters are most important for tagged
types because of dispatching-on-access-parameters (see 3.9.2). By
restricting this to formal parameters, we minimize problems
associated with allowing components that are not declared aliased to
be pointed-to from within the same record.
http://www.adaic.org/standards/95aarm/html/AA-3-10.html
--------------
A bug that ACT got rid of has been replaced with another bug in the same
place.
In 15 July 2001 I reported this error as a bug (in GNAT 3.13p, the native
FreeBSD version of FreeBSD):
| 5. function Nim (Omicron : Natural) return String renames Natural'Image;
| |
| >>> warning: "Omicron" is not referenced
With version 3.15p, there is still a warning (a minor problem):
| 17. function Nim (Omicron : Natural) return String
| 18. renames Natural'Image;
| |
| >>> (style): subprogram body has no previous spec
G. A. Craig Carey
Speedy Ada Strings.
(The licence of the package changed: this software now can't be mixed with
software under a licence having the acronym "GMPL", with 2 exceptions: (1)
Ada Core Tech software is OK, it's exempted; (2) the "GMPL" text per
file, of the 3rd party, is cryptographically signed by Ada Core, etc.
R. R. Software seems to have its own GMPL -- I didn't see the acronym
expanded, and while undefined it is different enough under law):
http://www.ijs.co.nz/code/ada95_strings_pkg.zip
http://www.ijs.co.nz/ada_95.htm
next prev parent reply other threads:[~2003-02-09 4:39 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-02-07 14:15 Representing data differently Daniel Allex
2003-02-07 18:07 ` tmoran
2003-02-09 4:39 ` Craig Carey [this message]
2003-02-10 12:47 ` Colin Paul Gloster
2003-02-13 17:21 ` Craig Carey
2003-02-08 0:24 ` Wojtek Narczynski
2003-02-12 18:52 ` Martin Krischik
2003-02-22 19:09 ` Robert A Duff
2003-02-23 13:06 ` Martin Krischik
2003-02-23 21:09 ` Craig Carey
2003-02-23 21:59 ` tmoran
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox