我有一个带有2个值type Polarity is (Normal, Reversed)
的Ada枚举,我想将它们分别转换为0,1(或者True,False - 因为布尔似乎隐含地扮演了很好的二进制),所以我可以将它们的值存储为一个字节中的特定位。我怎么能做到这一点?
答案 0 :(得分:3)
3.5.5 Operations of Discrete Types包含function S'Pos(Arg : S'Base)
,其中“返回Arg
的值的位置编号,作为通用整数类型的值。”因此,
Polarity'Pos(Normal) = 0
Polarity'Pos(Reversed) = 1
您可以使用13.4 Enumeration Representation Clauses更改编号。
......当然还有:
Boolean'Val(Polarity'Pos(Normal)) = False
Boolean'Val(Polarity'Pos(Reversed)) = True
答案 1 :(得分:3)
一种简单的方法是查找表:
Bool_Polarity : constant Array(Polarity) of Boolean
:= (Normal=>False, Reversed => True);
然后将其用作
B Boolean := Bool_Polarity(P);
当然使用'Pos属性没有任何问题,但是LUT使得映射可读且非常明显。
由于它是常数,你希望它在恒定折叠阶段期间优化掉,它似乎:我已经使用类似的技巧编译AVR具有非常可接受的可执行尺寸(低至0.6k以独立驱动2步进电机)
答案 2 :(得分:2)
我认为你要找的是带有表示子句的记录类型:
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位记录类型。
答案 3 :(得分:1)
这里有两点:
1)枚举已存储为二进制。一切都是。特别是,如上所述,您的枚举将存储为0
的{{1}}和Normal
的{{1}},除非您不遗余力地告诉编译器使用其他值。
如果要将枚举值中的值作为1
而不是枚举值,则有两个选项。 Reversed
属性将为枚举在枚举中的位置返回一个从0开始的数字,Integer
将返回计算机为其存储的实际值。 (除非使用了枚举表示子句,否则值没有区别。)
2)枚举很好,但不会重新发明'pos()
。如果您的枚举只能有两个值,那么通过自定义枚举不会获得任何有用的东西,并且会丢失Unchecked_Conversion
所具有的许多有用属性。可以直接从循环和Boolean
检查中选择布尔值。布尔人为他们定义了Boolean
,if
,and
等。布尔值可以放入打包数组中,然后在整个数组中按位定义相同的运算符。
我的一个特别的烦恼是当人们最终定义自己的逻辑反转的自定义布尔值时(因此其真实条件为0)。如果你这样做,Ada Lovelace的幽灵将从坟墓中回来并迫使你听取有关如何用差异引擎计算伯努利序列的详尽解释。不要让这件事发生在你身上!
因此,如果拥有第三个枚举值永远不会有意义,您只需将对象命名为适当的描述or
条件(例如:xor
),然后去在你快乐的路上。
答案 4 :(得分:0)
我需要做的就是pragma Pack([type name]);
(其中'type name'是由Polarity组成的类型)将值压缩为单个位。