From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,45a9122ddf5fcf5 X-Google-Attributes: gid103376,public From: dewar@cs.nyu.edu (Robert Dewar) Subject: Re: Rules for Representation of Subtypes Date: 1996/09/24 Message-ID: #1/1 X-Deja-AN: 185165525 references: <01bba947$d8990620$188371a5@dhoossr.iquest.com> organization: Courant Institute of Mathematical Sciences newsgroups: comp.lang.ada Date: 1996-09-24T00:00:00+00:00 List-Id: Matthew Heaney wrote in article mheaney-ya023080002209961353500001@news.ni.net>... I've always been curious about the rules for representation of subtypes. For example, if I make a declaration like this: A_Small_Integer : Integer range 0 .. 255; -- assume type Integer is 4 ytes then is an implementation allowed to use fewer than 4 bytes to represent A_Small_Integer? Suppose I'm on a Unix system and I do this read (fd, A_Small_Integer'Address, 4); If the representation of A_Small_Integer is only 1 byte, then obviously 'm in trouble. Am I required to specify the size of objects? A_Small_Integer : Integer range 0 .. 255; for A_Small_Integer'Size use 32; -- required? matt mheaney@ni.net David wrote Hi Matthew, My understanding of the rules for representation clauses for types is that the size attribute may only be specified for the first subtype, so for any subtype of integer you would get the same size as Integer. In fact, I just tried to specify a size of 8 bits for your object "A_Small_Integer", with gnat 3.04a on Win95, and found that the compiler gave no warning, and ignored the clause. Printing out the 'size attribute yielded 32. However, as far as your "UNIX" example is concerned (I say "UNIX", because this would apply to any OS where you're doing what you appear to be doing here -- i.e. interfacing to the C library), why not write the code in a manner where it doesn't matter how the compiler represents the object -- i.e., write: read (fd, A_Small_Integer'Address, A_Small_Integer'Size / System.Storage_Unit); The division is a compile-time operation, so there is no run-time difference. I hope this helps David's understanding is a bit confused, and so may not help :-) This in fact is a place where Ada 95, somewhat accidentally, is incompatible with most Ada 83 implementations. What Ada 95 did was to specify things that are left unspecified in the Ada 83 reference manual, and to do it in a manner that was compatible with the Intermetrics compiler, but not most other Ada 83 compilers, so this is something to be on the watch for. David's first significant misunderstanding is that the size of an object is not strongly related to the size of the type. So of course in GNAT, if you specify the size of an object as 8, it will be 8, but this will not affect the size of the type. Second, in Ada 95, the size of a subtype is required to be the minimum number of bits, so it is NOT AT ALL the case that a subtype has the same size as the first subtype. On the contrary, this would be an incorrect implementation. For example, Natural'Size is required to be Integer'Size MINUS ONE, i.e. 31, not 32, on most machines. This can cause chaos if a program assumes that Natural'Size is 32, as it was on many Ada 83 implementations. In GNAT, we have implemented the Size attribute as described in the RM, but generally the behavior of size is rather odd to most people: type x is range 1 .. 10; -- x'size = 4 subtype y is x range 1 .. 10; -- y'size = 4 subtype z is x range 1 .. 9; -- z'size = 4 Now use a size attribute clause type x is range 1 .. 10; -- x'size = 16 for x'size use 16; subtype y is x range 1 .. 10; -- y'size = 16 subtype z is x range 1 .. 9; -- z'size = 4 -- Suppose I'm on a Unix system and I do this read (fd, A_Small_Integer'Address, 4); Normally, you don't need to worry about the size of things, but if you are interfacing to C, you ought to specify the size of the object, or in this case, not simply use (A_Small_Integer'Size + Storage_Unit - 1)/Storage_Unit for 4. This is similar to David's suggestion, except that he made an unjustified assumption that the size of A_SMall_Integer would be a multiple of Storage Unit. Incidentally, we have considered adding an attribute Size_In_Storage_Units to GNAT. It is annoyingly missing, and would often be useful.