跳轉到內容

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 提供的函式或過程的例項。

請注意,標量儲存順序僅影響記憶體中的資料表示。它對流屬性使用的表示沒有影響。

請注意,偵錯程式可能無法顯示為指定了相反儲存順序的型別的標量元件的正確值。

華夏公益教科書