跳转到内容

Ada 编程/属性/'标量存储顺序

来自维基教科书,自由的教科书

对于每个数组或记录类型 S,表示属性 Scalar_Storage_Order 表示组成标量组件的存储元素在 S 中的顺序。给定的值必须是类型 System.Bit_Order 的静态表达式。以下是一个使用此功能的示例

--  Component type definitions

subtype Yr_Type is Natural range 0 .. 127;
subtype Mo_Type is Natural range 1 .. 12;
subtype Da_Type is Natural range 1 .. 31;

--  Record declaration

type Date is record
   Years_Since_1980 : Yr_Type;
   Month            : Mo_Type;
   Day_Of_Month     : Da_Type;
end record;

--  Record representation clause

for Date use record
   Years_Since_1980 at 0 range 0  ..  6;
   Month            at 0 range 7  .. 10;
   Day_Of_Month     at 0 range 11 .. 15;
end record;

--  Attribute definition clauses

for Date'Bit_Order use System.High_Order_First;
for Date'Scalar_Storage_Order use System.High_Order_First;
--  If Scalar_Storage_Order is specified, it must be consistent with
--  Bit_Order, so it's best to always define the latter explicitly if
--  the former is used.

其他属性与 Ada RM 13.5.3(4) 定义的标准表示属性 Bit_Order 相同。默认值为 System.Default_Bit_Order

对于记录类型 T,如果显式指定了 T'Scalar_Storage_Order,则它应等于 T'Bit_Order。注意:这意味着如果 Scalar_Storage_Order 属性定义子句未确认,则类型的 Bit_Order 应显式指定并设置为相同的值。

派生类型从其父类型继承显式设置的标量存储顺序。可以通过为派生类型提供显式标量存储顺序来覆盖此顺序。但是,对于记录扩展,派生类型必须具有与父类型相同的标量存储顺序。

记录类型的组件本身是记录或数组,并且没有以字节边界开始和结束的组件,必须具有与记录类型相同的标量存储顺序。位打包数组类型的组件本身是记录或数组,必须具有与数组类型相同的标量存储顺序。

具有显式 Scalar_Storage_Order 属性定义的类型的任何组件都不能别名化。

确认的 Scalar_Storage_Order 属性定义子句(即,值为 System.Default_Bit_Order)没有影响。

如果指定了相反的存储顺序,则每当读取类型 S 的对象的标量组件的值时,封闭的机器标量的存储元素将首先被反转(在检索组件值之前,可能在封闭的机器标量上应用一些移位和掩码操作),并且对写入执行相反的操作。

在这种情况下,对标量组件的 13.5.1(10.3/2) 中规定的限制被放宽。相反,以下规则适用

  • 底层存储元素位于位置 (position + first_bit / storage_element_size) .. (position + (last_bit + storage_element_size - 1) / storage_element_size)
  • 底层存储元素的序列的大小不应大于最大的机器标量
  • 封闭的机器标量定义为从位置不超过 position + first_bit / storage_element_size 开始并至少覆盖存储元素到 position + (last_bit + storage_element_size - 1) / storage_element_size 的最小的机器标量
  • 组件的位置相对于该机器标量进行解释。

如果未为类型指定标量存储顺序(无论是直接指定还是通过继承在派生类型的情况下),则默认值通常是目标的本机顺序,但此默认值可以使用 pragma Default_Scalar_Storage_Order 覆盖。

如果 T 的组件本身是记录或数组类型,则指定的 Scalar_Storage_Order 应用于该嵌套类型:如果需要,也必须为组件类型提供显式属性定义子句。

显式或隐式切换标量存储顺序的表示更改不受支持,可能会导致程序执行错误,除非通过 Ada.Unchecked_Conversion 的实例执行。

特别是,覆盖不受支持,并且会为此发出警告

type Rec_LE is record
   I : Integer;
end record;

for Rec_LE use record
   I at 0 range 0 .. 31;
end record;

for Rec_LE'Bit_Order use System.Low_Order_First;
for Rec_LE'Scalar_Storage_Order use System.Low_Order_First;

type Rec_BE is record
   I : Integer;
end record;

for Rec_BE use record
   I at 0 range 0 .. 31;
end record;

for Rec_BE'Bit_Order use System.High_Order_First;
for Rec_BE'Scalar_Storage_Order use System.High_Order_First;

R_LE : Rec_LE;

R_BE : Rec_BE;
for R_BE'Address use R_LE'Address;

警告:覆盖更改标量存储顺序 [默认情况下启用]

在大多数情况下,此类表示更改应替换为 GNAT.Byte_Swapping 提供的函数或过程的实例。

请注意,标量存储顺序仅影响内存中的数据表示。它对流属性使用的表示没有影响。

请注意,调试器可能无法显示为指定了相反存储顺序的类型的标量组件的正确值。

华夏公益教科书