位域的Ada模式

位域的Ada模式,ada,Ada,在C语言中,使用某种形式的无符号字符或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 B

在C语言中,使用某种形式的无符号字符或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;

这看起来有点笨重。有没有更好、更可爱的方式来使用这样的位图?

您的位域到底想要实现什么?您似乎想使用Ada编写C。如果这是真的,那么考虑在艾达中使用模块化类型,在C.

中使用无符号类型。 Ada 2012参考手册第4.5.1节规定:

对于模块化类型,预定义的逻辑运算符在 以位为基础,使用二进制表示 用于生成结果的二进制表示形式的操作数,其中为零 表示假,表示真。如果这个结果是外部的 类型的基本范围,最后由模数减去 执行以将结果带入类型的基本范围

阵列上的逻辑运算符是在 组件对组件的基础上匹配组件作为平等- 参见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#;
现在,您可以对颜色矩阵的实例执行所有熟悉的操作

编辑:
比较Ada表示子句和C/C++位字段的其他信息可以在

中找到,您实际想用位字段实现什么?您似乎想使用Ada编写C。如果这是真的,那么考虑在艾达中使用模块化类型,在C.

中使用无符号类型。 Ada 2012参考手册第4.5.1节规定:

对于模块化类型,预定义的逻辑运算符在 以位为基础,使用二进制表示 用于生成结果的二进制表示形式的操作数,其中为零 表示假,表示真。如果这个结果是外部的 类型的基本范围,最后由模数减去 执行以将结果带入类型的基本范围

阵列上的逻辑运算符是在 组件对组件的基础上匹配组件作为平等- 参见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#;
现在,您可以对颜色矩阵的实例执行所有熟悉的操作

编辑:
比较Ada表示子句和C/C++位字段的其他信息可以在

中找到。它确实取决于您尝试执行的操作

通常,您会看到反复使用&| ~>运算符,有时甚至是&&| |,并且很容易在C中获得错误的掩码值来设置、清除或测试单个位,例如在位字段类型中打开或关闭红色,而不是直接访问位:

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

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

这取决于您尝试执行的操作

通常,您会看到反复使用&| ~>运算符,有时甚至是&&| |,并且很容易在C中获得错误的掩码值来设置、清除或测试单个位,例如在位字段类型中打开或关闭红色,而不是直接访问位:

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;

我真的不应该把周六的时间花在给学生做作业上-

尽量移动到声明部分。您可以这样做:

-- 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;

pragma包是一个提示,编译器可以随意忽略它。您要为BitFieldType'Component\u大小使用1;相反,一点也不笨重!它非常实用,特别是对于大型枚举类型。GNAT和其他编译器可能会为此生成非常高效的机器代码。我只编写COLOR_集而不是BITFELDTYPE和Purple_集等,而不是PIPPLEBITFELD。您更多地考虑数学对象,而较少考虑它是如何实现的……pragma包是一个提示,编译器可以随意忽略它。您要为BitFieldType'Component\u大小使用1;相反,一点也不笨重!它非常实用,特别是对于大型枚举类型。GNAT和其他编译器可能会为此生成非常高效的机器代码。我只编写COLOR_集而不是BITFELDTYPE和Purple_集等,而不是PUPPLEBITFIEL
D您更多地考虑数学对象,而较少考虑它是如何实现的……很容易使这些二进制值出错!不像在C语言中用hexTrue编写代码那么简单,但这就是为什么我使用二进制表示法,并将代码格式化为一个表,这样人们就可以更容易地直观地检查值。很容易让那些二进制值出错!不像在C中用hexTrue编写代码那样简单,但这就是为什么我使用二进制表示法,并将代码格式化为一个表,以便更容易直观地检查值。