位域的Ada模式

问题描述

在C语言中,使用无符号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;

这看起来有些笨拙。是否有更好和更多的Lovelacey方法来使用像这样的位图?

解决方法

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

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

对于模块化类型,预定义的逻辑运算符在 逐位使用值的二进制表示形式 操作数产生结果的二进制表示形式,其中零 代表False,一个代表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#;

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

编辑: 可以在https://sworthodoxy.blogspot.com/2014/03/ada-vs-c-bit-fields.html

中找到比较Ada表示子句和C / C ++位域的其他信息。 ,

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

通常,您会发现& | ~ << >>运算符(有时甚至是&& ||)的使用令人费解,并且在C中容易设置错误的掩码值用于设置,清除或测试单个位(例如,在BitFieldType中打开或关闭RED),而不是直接访问该位:

MyBitField(Red) := TRUE;
If MyBitField(Orange) then ...

很有趣的是,对于具有位设置,清除和测试指令的微控制器,编译器将C代码转换为显而易见的简单指令是一项艰巨的工作。

,

我真的不应该花星期六做学生作业! ;-)

尝试将其尽可能移到声明部分。您可以这样做:

-- Warning: Not tested
with Ada.Text_IO;

procedure Bit_Fields is

   type Typ_Counter is range 0 .. 1_000_000; --  Fix this!
   package Counter_Io is new Ada.Text_Io.Integer_Io (Typ_Counter);

   procedure Increment (Counter : in out Typ_Counter; On_Condition : Boolean) is
   begin
      if On_Condition then
         Counter := Counter + 1;  --  May overflow!
      end if;
   end Increment;


   type Typ_Colour is mod 2**8 with Size => 8;  --  Look into this!

   Colour_Max  : constant Typ_Colour := Typ_Colour'Last;
   Colour_None : constant Typ_Colour := Typ_Colour'First;


   type Knd_Colour is (Red,Green,Blue,Orange,Yellow,Purple);
   type Arr_Colour is array (Knd_Colour) of Typ_Colour;

   None        : constant Arr_Colour := (others => Colour_None);
   Max         : constant Arr_Colour := (others => Colour_Max);

   generic
      with function Operation (Left,Right : Typ_Colour) return Typ_Colour;
   function Generic_Operation (Left,Right : Arr_Colour) return Arr_Colour;

   function Generic_Operation (Left,Right : Arr_Colour) return Arr_Colour
   is
      Result : Arr_Colour;
   begin
      for Gun in Result'Range loop
         Result (Gun) := Operation (Left  => Left  (Gun),Right => Right (Gun));
      end loop;
      return Result;
   end Generic_Operation;


   function "or"  is new Generic_Operation (Operation => "or");
   function "and" is new Generic_Operation (Operation => "and");

   My_Colours       : Arr_Colour;
   My_Other_Colours : Arr_Colour;
   Counter          : Typ_Counter := 0;
begin
   My_Colours       := (Red => not Colour_Max,others => Colour_None);
   My_Other_Colours := (Red => Colour_Max,others => Colour_None);

   Increment (Counter,On => (My_Other_Colours or My_Colours)        = Max);
   Increment (Counter,On => (My_Colours       and My_Other_Colours) = None);

   declare
      use Ada.Text_Io,Counter_IO;
   begin
      Put ("Counter is ");
      Put (Counter,Width => 0);
      New_Line;
   end;

end Bit_Fields;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...