私は2つの値を持つAda列挙型を持っており、type Polarity is (Normal, Reversed)
それらをそれぞれ0、1(またはTrue、False-ブール値は暗黙的にバイナリとして適切に再生されるように見えるため)に変換したいので、それらの値を特定のビットとしてバイト。どうすればこれを達成できますか?
5 に答える
簡単な方法はルックアップテーブルです。
Bool_Polarity : constant Array(Polarity) of Boolean
:= (Normal=>False, Reversed => True);
その後、それをとして使用します
B Boolean := Bool_Polarity(P);
もちろん、'Pos属性を使用しても問題はありませんが、LUTを使用すると、マッピングが読みやすく、非常にわかりやすくなります。
それは一定であるため、定数畳み込み段階で最適化されることを望んでいます。私は、非常に許容可能な実行可能サイズ(2つのステッピングモーターを独立して駆動するために0.6kまで)でAVR用にコンパイルする同様のトリックを使用しました。
3.5.5離散型の演算には、「の値の位置番号を、型ユニバーサル整数function S'Pos(Arg : S'Base)
の値として返す」が含まれ。したがって、Arg
Polarity'Pos(Normal) = 0
Polarity'Pos(Reversed) = 1
13.4列挙表現句を使用して番号を変更できます。
...そしてもちろん:
Boolean'Val(Polarity'Pos(Normal)) = False
Boolean'Val(Polarity'Pos(Reversed)) = True
あなたが探しているのは、表現句のあるレコードタイプだと思います。
procedure Main is
type Byte_T is mod 2**8-1;
for Byte_T'Size use 8;
type Filler7_T is mod 2**7-1;
for Filler7_T'Size use 7;
type Polarity_T is (Normal,Reversed);
for Polarity_T use (Normal => 0, Reversed => 1);
for Polarity_T'Size use 1;
type Byte_As_Record_T is record
Filler : Filler7_T;
Polarity : Polarity_T;
end record;
for Byte_As_Record_T use record
Filler at 0 range 0 .. 6;
Polarity at 0 range 7 .. 7;
end record;
for Byte_As_Record_T'Size use 8;
function Convert is new Ada.Unchecked_Conversion
(Source => Byte_As_Record_T,
Target => Byte_T);
function Convert is new Ada.Unchecked_Conversion
(Source => Byte_T,
Target => Byte_As_Record_T);
begin
-- TBC
null;
end Main;
Byte_As_Record_T
&Byte_T
は同じサイズなので、タイプ間を安全に変換するために使用できますunchecked conversion
。
の表現句をByte_As_Record_T
使用すると、配置するビット/バイトを指定できますpolarity_t
。(8番目のビットを選択しました)
私の定義はByte_T
あなたが望むものではないかもしれませんが、それが8ビットの長さである限り、原則はまだ機能するはずです。Byte_Tから、またはに安全にアップキャストすることもInteger
できNatural
ますPositive
。同じ手法を使用して、32ビット整数と32ビットレコードタイプとの間で直接移動することもできます。
ここで2つのポイント:
1)列挙型はすでにバイナリとして格納されています。すべてです。特に、上記で定義した列挙は、コンパイラに他の値を使用するように指示しない限り、 0
forNormal
および1
forとして格納されます。Reversed
その値をInteger
列挙値ではなく列挙値として取得する場合は、2つのオプションがあります。この'pos()
属性は、列挙内のその列挙の位置に対して0から始まる数値Unchecked_Conversion
を返し、コンピューターがその列挙に格納する実際の値を返します。(列挙表現句が使用されていない限り、値に違いはありません)。
2)列挙は素晴らしいですが、再発明しないBoolean
でください。列挙型が2つの値しか持てない場合、カスタム列挙型を作成しても有用なものは何も得られず、持つ多くの有用なプロパティが失われBoolean
ます。if
ブール値は、ループとチェックから直接選択できます。ブール値には、、、などand
が定義されています。ブール値をパックされた配列に入れることができ、それらの同じ演算子が配列全体でビット単位で定義されます。or
xor
私の特定のペットピーブは、人々が論理を逆にしてカスタムブール値を定義することになったときです(したがって、その真の条件は0です)。これを行うと、エイダ・ラブレスの幽霊が墓から戻ってきて、階差機関でベルヌーイシーケンスを計算する方法の徹底的な説明を聞くように強制されます。これをあなたに起こさせないでください!
したがって、3番目の列挙値を使用しても意味がない場合は、オブジェクトに条件を説明する適切な名前をTrue
付けて(例Reversed_Polarity : Boolean;
:)、陽気な方法で進めます。
私がする必要がpragma Pack([type name]);
あるのは(「タイプ名」は極性で構成されるタイプです)、値を1ビットに圧縮することだけだったようです。