Next: Pragma Pack for Records, Previous: Effect of Bit_Order on Byte Ordering, Up: Representation Clauses and Pragmas
Pragma Pack
applied to an array has no effect unless the component type
is packable. For a component type to be packable, it must be one of the
following cases:
For all these cases, if the component subtype size is in the range
1 through 63, then the effect of the pragma Pack
is exactly as though a
component size were specified giving the component subtype size.
For example if we have:
type r is range 0 .. 17; type ar is array (1 .. 8) of r; pragma Pack (ar);
Then the component size of ar
will be set to 5 (i.e. to r'size
,
and the size of the array ar
will be exactly 40 bits.
Note that in some cases this rather fierce approach to packing can produce
unexpected effects. For example, in Ada 95, type Natural typically has a
size of 31, meaning that if you pack an array of Natural, you get 31-bit
close packing, which saves a few bits, but results in far less efficient
access. Since many other Ada compilers will ignore such a packing request,
GNAT will generate a warning on some uses of pragma Pack
that it guesses
might not be what is intended. You can easily remove this warning by
using an explicit Component_Size
setting instead, which never generates
a warning, since the intention of the programmer is clear in this case.
GNAT treats packed arrays in one of two ways. If the size of the array is known at compile time and is less than 64 bits, then internally the array is represented as a single modular type, of exactly the appropriate number of bits. If the length is greater than 63 bits, or is not known at compile time, then the packed array is represented as an array of bytes, and the length is always a multiple of 8 bits.
Note that to represent a packed array as a modular type, the alignment must be suitable for the modular type involved. For example, on typical machines a 32-bit packed array will be represented by a 32-bit modular integer with an alignment of four bytes. If you explicitly override the default alignment with an alignment clause that is too small, the modular representation cannot be used. For example, consider the following set of declarations:
type R is range 1 .. 3; type S is array (1 .. 31) of R; for S'Component_Size use 2; for S'Size use 62; for S'Alignment use 1;
If the alignment clause were not present, then a 62-bit modular representation would be chosen (typically with an alignment of 4 or 8 bytes depending on the target). But the default alignment is overridden with the explicit alignment clause. This means that the modular representation cannot be used, and instead the array of bytes representation must be used, meaning that the length must be a multiple of 8. Thus the above set of declarations will result in a diagnostic rejecting the size clause and noting that the minimum size allowed is 64.
One special case that is worth noting occurs when the base type of the
component size is 8/16/32 and the subtype is one bit less. Notably this
occurs with subtype Natural
. Consider:
type Arr is array (1 .. 32) of Natural; pragma Pack (Arr);
In all commonly used Ada 83 compilers, this pragma Pack would be ignored,
since typically Natural'Size
is 32 in Ada 83, and in any case most
Ada 83 compilers did not attempt 31 bit packing.
In Ada 95, Natural'Size
is required to be 31. Furthermore, GNAT really
does pack 31-bit subtype to 31 bits. This may result in a substantial
unintended performance penalty when porting legacy Ada 83 code. To help
prevent this, GNAT generates a warning in such cases. If you really want 31
bit packing in a case like this, you can set the component size explicitly:
type Arr is array (1 .. 32) of Natural; for Arr'Component_Size use 31;
Here 31-bit packing is achieved as required, and no warning is generated, since in this case the programmer intention is clear.