Pragma Pack for Arrays (GNAT Reference Manual)

### 9.10 Pragma Pack for Arrays ¶

Pragma `Pack` applied to an array has an effect that depends upon whether the component type is ‘packable’. For a component type to be ‘packable’, it must be one of the following cases:

- Any elementary type.
- Any small packed array type with a static size.
- Any small simple record type with a static size.

For all these cases, if the component subtype size is in the range 1 through 63 on 32-bit targets, and 1 through 127 on 64-bit targets, then the effect of the pragma `Pack` is exactly as though a component size were specified giving the component subtype size.

All other types are non-packable, they occupy an integral number of storage units and the only effect of pragma Pack is to remove alignment gaps.

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 and Ada 2005, subtype `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 at most 64 bits on 32-bit targets, and at most 128 bits on 64-bit targets, then internally the array is represented as a single modular type, of exactly the appropriate number of bits. If the length is greater than 64 bits on 32-bit targets, and greater than 128 bits on 64-bit targets, or is not known at compile time, then the packed array is represented as an array of bytes, and its 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 and Ada 2005, `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.