Types 将分离字段合并为一个字段

Types 将分离字段合并为一个字段,types,ada,Types,Ada,我在Ada工作,我有一个非常难看的类型,我不能修改,我想做一些简单易用的事情 类型如下所示: for T_Ugly_Type'Alignment use 4; for T_Ugly_Type'Size use 48; for T_Ugly_Type use record Value_Bits_00_07 at 16#00# range 0 .. 7; -- 8 bits Field1 at 16#00# range 8 .. 15; -- 8 b

我在Ada工作,我有一个非常难看的类型,我不能修改,我想做一些简单易用的事情

类型如下所示:

for T_Ugly_Type'Alignment use 4;
for T_Ugly_Type'Size use 48;
for T_Ugly_Type use record
    Value_Bits_00_07  at 16#00# range 0  .. 7;   -- 8 bits
    Field1            at 16#00# range 8  .. 15;  -- 8 bits

    Field2            at 16#02# range 0  .. 11;  -- 12 bits
    Value_Bits_08_11  at 16#02# range 12 .. 15;  -- 4 bits

    Value_Bits_12_15  at 16#03# range 0  .. 3;   -- 4 bits
    Field3            at 16#03# range 4 .. 15;   -- 12 bits
end record;
此结构由消息填充,地址无法更改。但我的值是一个16位类型,分为3部分。我不想把所有这些零件都浓缩成我想用的每种类型


有没有一种方法可以使用T_丑陋_Type.Value并获得值_Bits_00_07+2**8*值_Bits_08_12+2**12*值_Bits_12_15的结果?

您可以这样做:

type T_Wrapper is tagged record
   Values : T_Ugly_Type;
end record;

function Value (Subject : T_Wrapper) return Uint16 is
  (Subject.Values.Value_Bits_00_07 * 2**8 +
          Subject.Values.Value_Bits_08_12 * 2**4 +
          Subject.Values.Vaule_Bits_13_15);

function Field1 (Subject : T_Wrapper) return Uint12 is
  (Subject.Values.Field1);

function Field2 (Subject : T_Wrapper) return Uint12 is
  (Subject.Values.Field2);

function Field3 (Subject : T_Wrapper) return Uint12 is
  (Subject.Values.Field3);
标记使您能够在T_包装函数上使用前缀语法:

declare
   -- assuming a T_Ugly_Type instance named Orig
   Wrapped : T_Wrapper := (Values => Orig);
begin
   Do_Something (Wrapped.Value);
   Do_Something_Elese (Wrapped.Field1);
end;
请注意,由于原始类型没有标记,因此不能在其上声明值函数,可以使用前缀表示法调用

一种更好的方法是使用访问值和一些Ada 2012功能:

type Reference (Data : not null access T_Ugly_Type) is tagged limited null record
  with Implicit_Dereference => Data;

function Value (Subject : Reference) return Uint16 is
  (Subject.Data.Value_Bits_00_07 * 2**8 +
   Subject.Data.Value_Bits_08_12 * 2**4 +
   Subject.Data.Vaule_Bits_13_15);
隐式解引用允许您直接访问原始字段,同时可以使用Value函数进行计算

declare
   Ref : Reference := (Data => Orig'Access);
begin
   Do_Something (Ref.Value); -- calls function
   Do_Something (Ref.Field1); -- accesses Field1 of the inner record
end;

你到底想问什么?如何在新结构中转换原有结构?价值的持久性是什么?为什么值\u Bits\u 08\u 12注释为4位,而实际上它只填充3位13..15?@flyx我修改了我的问题,希望它更清楚。谢谢你的回答,函数值是一个getter,但有没有实现setter的方法?函数是这样工作的,因为如果你不传递任何参数,你就不会写。setter是一个过程Set_值:Uint16;您不能像C属性那样实现它,在C属性中,您分配值并隐式调用setter。