Ada types size difference

2019-09-18 20:00发布

问题:

I have this Ada program:

with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure test is
type MY_TYPE is new Integer range 1..20;
subtype MY_TYPE2 is MY_TYPE range 5..6;
c : MY_TYPE:=10;
 f : MY_TYPE2 :=6;
 begin
put(Integer(c'SIZE));
 end test;

and when I run it I get 32. If I replace

type MY_TYPE is new Integer range 1..20;

with

type MY_TYPE is range 1..20;

I get 8. What is the difference between the two declarations?

回答1:

You are allowing the compiler to choose the sizes for these different type declarations, and it is picking the size of your INTEGER type according to the size of its base type (INTEGER).

You have control over the sizes of these types : if you rewrite the first declaration as

type MY_TYPE is new Integer range 1..20;
for MYTYPE'SIZE use 8;

you should get an 8-bit MY_TYPE.

for MYTYPE'SIZE use 5;

ought to pack MYTYPE into 5 bits (as I understand it, a compiler is permitted to reject this with an explicit error, or generate correct code, but NOT to accept it and generate garbage.)

Why would you want to pack MYTYPE into 5 bits? One reason is if it's used as a component of a record : that leaves room for 3 more components in a single byte, as long as they are booleans and their SIZE attribute is 1!

This may look like extreme packing, but it's actually quite common in embedded programming, where that record type matches the bits in a peripheral or I/O port. You would also specify the bit-level layout within the record, as in:

type Prescale is new Integer range 1..20;
for  Prescale'SIZE use 5;

type Timer_Ctrl_Reg is record
   Scale  : Prescale;
   Up     : Boolean;
   Repeat : Boolean;
   Int_En : Boolean;
end record;
for Timer_Ctrl_Reg use record
   Scale  at 0 range 0 .. 4;
   Up     at 0 range 5 .. 5;
   Repeat at 0 range 6 .. 6;
   Int_En at 0 range 7 .. 7;
end record;

at specifies the offset from the record base in "storage units" usually bytes or words : range specifies the bit positions within the storage unit.

No more dodgy bit masking and extraction to worry about!

On the other hand,

for MYTYPE'SIZE use 4;

ought to fail, as MYTYPE has more than 16 discrete values.



回答2:

This:

type MY_TYPE is new Integer range 1..20;

explicitly inherits MY_TYPE from Integer, which apparently is 32 bits on your system.

This:

type MY_TYPE is range 1..20;

leaves it up to the compiler to decide what to inherit MY_TYPE from how to represent MY_TYPE. The result is implementation-specific; apparently your compiler chooses to implement it as an 8-bit integer type.



标签: size ada