Bit_Order Clauses (GNAT Reference Manual) (original) (raw)
9.8 Bit_Order Clauses ¶
For record subtypes, GNAT permits the specification of the Bit_Order
attribute. The specification may either correspond to the default bit order for the target, in which case the specification has no effect and places no additional restrictions, or it may be for the non-standard setting (that is the opposite of the default).
In the case where the non-standard value is specified, the effect is to renumber bits within each byte, but the ordering of bytes is not affected. There are certain restrictions placed on component clauses as follows:
- Components fitting within a single storage unit.
These are unrestricted, and the effect is merely to renumber bits. For example if we are on a little-endian machine withLow_Order_First
being the default, then the following two declarations have exactly the same effect:
type R1 is record
A : Boolean;
B : Integer range 1 .. 120;
end record;
for R1 use record
A at 0 range 0 .. 0;
B at 0 range 1 .. 7;
end record;
type R2 is record
A : Boolean;
B : Integer range 1 .. 120;
end record;
for R2'Bit_Order use High_Order_First;
for R2 use record
A at 0 range 7 .. 7;
B at 0 range 0 .. 6;
end record;
The useful application here is to write the second declaration with theBit_Order
attribute definition clause, and know that it will be treated the same, regardless of whether the target is little-endian or big-endian. - Components occupying an integral number of bytes.
These are components that exactly fit in two or more bytes. Such component declarations are allowed, but have no effect, since it is important to realize that theBit_Order
specification does not affect the ordering of bytes. In particular, the following attempt at getting an endian-independent integer does not work:
type R2 is record
A : Integer;
end record;
for R2'Bit_Order use High_Order_First;
for R2 use record
A at 0 range 0 .. 31;
end record;
This declaration will result in a little-endian integer on a little-endian machine, and a big-endian integer on a big-endian machine. If byte flipping is required for interoperability between big- and little-endian machines, this must be explicitly programmed. This capability is not provided byBit_Order
. - Components that are positioned across byte boundaries.
but do not occupy an integral number of bytes. Given that bytes are not reordered, such fields would occupy a non-contiguous sequence of bits in memory, requiring non-trivial code to reassemble. They are for this reason not permitted, and any component clause specifying such a layout will be flagged as illegal by GNAT.
Since the misconception that Bit_Order automatically deals with all endian-related incompatibilities is a common one, the specification of a component field that is an integral number of bytes will always generate a warning. This warning may be suppressed using pragma Warnings (Off)
if desired. The following section contains additional details regarding the issue of byte ordering.