位域的 Ada 模式

Chr*_*bbs 1 ada

在 C 中,使用某种形式的 unsigned char 或 int 位来表示非排他条件是很常见的,并且通过使用 & | 和 ~ 操作符,效率极高。根据我有限的 Ada 经验,Ada 中的等效项如下面的代码所示。

with Ada.Text_IO;   use Ada.Text_IO;

procedure Main is

   type Colours is (Red, Green, Blue, Orange, Yellow, Purple);

   type BitFieldType is array (Colours) of Boolean;
   pragma Pack (BitFieldType);

   RedBitField : constant BitFieldType := (Red => True, others => False);
   GreenBitField : constant BitFieldType := (Green => True, others => False);
   BlueBitField : constant BitFieldType := (Blue => True, others => False);
   OrangeBitField : constant BitFieldType := (Orange => True, others => False);
   YellowBitField : constant BitFieldType := (Yellow => True, others => False);
   PurpleBitField : constant BitFieldType := (Purple => True, others => False);
   NoColourBitField   : constant BitFieldType := (others => False);
   AllColoursBitField : constant BitFieldType := (others => True);

   MyBitField      : BitFieldType;
   MyOtherBitField : BitFieldType;
   Counter         : Integer := 0;

begin
   MyBitField      := not RedBitField;
   MyOtherBitField := RedBitField;

   if (MyOtherBitField or MyBitField) = AllColoursBitField then
      Counter := Counter + 1;
   end if;

   if (MyBitField and MyOtherBitField) = NoColourBitField then
      Counter := Counter + 1;
   end if;

   Put_Line ("Counter is " & Integer'image (Counter));

end Main;
Run Code Online (Sandbox Code Playgroud)

这显得有些笨拙。像这样使用位图有没有更好的、更 Lovelacey 的方式?

Jim*_*ers 6

你实际上想用你的位域实现什么?您似乎想使用 Ada 编写 C。如果这是真的,那么考虑在 Ada 中使用模块化类型,而您将在 C 中使用无符号类型。

Ada 2012 参考手册的第 4.5.1 节指出:

对于模块化类型,预定义的逻辑运算符是逐位定义的,使用操作数值的二进制表示来生成结果的二进制表示,其中零表示 False,1 表示 True。如果此结果在类型的基本范围之外,则执行模数的最终减法以将结果带入类型的基本范围。

数组上的逻辑运算符在匹配组件的基础上逐个组件执行(如相等性 — 参见 4.5.2),使用组件类型的预定义逻辑运算符。结果数组的边界是左操作数的边界。

例如,您的示例的无符号类型可以定义为

type Color_Matrix is mod 2**6;
Red        : constant Color_Matrix := 2#100000#;
Green      : constant Color_Matrix := 2#010000#;
Blue       : constant Color_Matrix := 2#001000#;
Orange     : constant Color_Matrix := 2#000100#;
Yellow     : constant Color_Matrix := 2#000010#;
Purple     : constant Color_Matrix := 2#000001#;
No_Color   : constant Color_Matrix := 0;
All_Colors : constant Color_Matrix := 2#111111#;
Run Code Online (Sandbox Code Playgroud)

您现在可以对 Color_Matrix 的实例执行所有熟悉的操作。

编辑: 可以在https://sworthodoxy.blogspot.com/2014/03/ada-vs-c-bit-fields.html 中找到比较 Ada 表示子句和 C/C++ 位域的其他信息


Bri*_*ond 6

这确实取决于您要尝试做什么。

通常你会看到在 C 中复杂地使用& | ~ << >>运算符(有时甚至是&& ||)和容易出错的掩码值来设置、清除或测试单个位(例如在 BitFieldType 中打开或关闭 RED)而不是访问位直接:

MyBitField(Red) := TRUE;
If MyBitField(Orange) then ...
Run Code Online (Sandbox Code Playgroud)

有趣的是,对于具有位设置、清除和测试指令的微控制器,编译器将 C 代码翻译成明显的简单指令是一项相当困难的工作。