Ada 将整数转换为记录

Ada 将整数转换为记录,ada,Ada,我从C中得到一个16位整数。这个整数由16个标志组成 如何在16个布尔值的记录中转换这个整数 谢谢 您只需执行16位右移和按位移位,结果为1,即可确定是否设置了位/标志。这里有一个例子(我希望这不是家庭作业): 可以使用包含短int(或int_16)和位字段的并集: union UMyFlags { short n; struct { flag_1 : 1; flag_2 : 1; // other flags ... }

我从C中得到一个16位整数。这个整数由16个标志组成

如何在16个布尔值的记录中转换这个整数


谢谢

您只需执行16位右移和按位移位,结果为1,即可确定是否设置了位/标志。这里有一个例子(我希望这不是家庭作业):


可以使用包含短int(或int_16)和位字段的并集:

union UMyFlags {
    short n;
    struct {
        flag_1 : 1;
        flag_2 : 1;
        // other flags ...
    } flags;
};
但是,由于字节顺序的原因,您的代码不会在每个平台上都是可移植的。

在Ada中,a允许逻辑操作以位集的形式访问值。Ada 95中介绍的概述可在中找到。根据实现的不同,预定义类型my可能是从C获取值的方便选择

type Flags is record
   Flag1 : Boolean;
   Flag2 : Boolean;
   - ...
   Flag15 : Boolean;
end record;

for Flags use record
   Flag1  at 0 range 0 .. 0;
   Flag2  at 0 range 1 .. 1;
   -- ...
   Flag15 at 0 range 15 .. 15;
 end record;
 for Flags'Size use 16;

 -- This is vital, because normally, records are passed by-reference in Ada.
 -- However, as we use this type with C, it has to be passed by value.
 -- C_Pass_By_Copy was introduced in GNAT and is part of the language since Ada 2005.
 pragma Convention (C_Pass_By_Copy, Flags);

您可以在C整数类型的导入C函数instad的声明中直接使用此类型。

在Ada中,您通常可以声明导入的函数以获取所需类型的参数或返回值,而不是随后必须转换的C等价类型

那么,这里,你想要什么

type Flags is array (0 .. 15) of Boolean;
for Flags'Component_Size use 1;
for Flags'Size use 16;
pragma Convention (C, Flags);
您可以将函数声明为

function Get_Flags return Flags;
pragma Import (C, Get_Flags, “get_flags");
其中

unsigned short get_flags(void) {
  return 0x6e8b;
}
一个简单的安全带给了我

flag 0 is TRUE
flag 1 is TRUE
flag 2 is FALSE
flag 3 is TRUE
flag 4 is FALSE
flag 5 is FALSE
flag 6 is FALSE
flag 7 is TRUE
flag 8 is FALSE
flag 9 is TRUE
flag 10 is TRUE
flag 11 is TRUE
flag 12 is FALSE
flag 13 is TRUE
flag 14 is TRUE
flag 15 is FALSE
正如Bo Persson所指出的,只要您的代码只需要在一台小小的endian机器上运行就可以了。如果你想让它在SPARC或Powerbook上运行,最好使用垃圾神的建议

subtype Flags is Interfaces.C.unsigned_short;
use type Flags;

function Get_Flags return Flags;
pragma Import (C, Get_Flags, "get_flags");
然后,也许,命名你的标志位(用一些更有意义的东西!)

或者(可能更像C)

然后检查

(Get_Flags and Flag_3) /= 0

您还可以使用叠加来实现所需的结果;让我们假设这些布尔值都是有意义的严格布尔值(也就是说,没有什么是枚举)

首先,您需要定义您的记录;我将用一个Nybble来说明,但原则是适用的。Nybble是旧的DOS属性:读取(可见性方面;回想起来应该是隐藏的)、写入、归档和系统

Type Nyble_Data is mod 2**4;
For Nyble_Data'Size use 4;

Type Data_Record is record
    Can_Read, Can_Write, Is_Archived, Is_System : Boolean:= False;
end record;

-- Ensure 4 bits used.
pragma Pack (Data_Record);
For Data_Record'Size use 4;

-- Specify Layout.
For Data_Record use
    record
        Can_Read    at 0 range 0..0;
        Can_Write   at 0 range 1..1;
        Is_Archived at 0 range 2..2;
        Is_System   at 0 range 3..3;
    end record;

-- This is where the magic occurs.
Function Convert( Data : In Nyble_Data ) Return Data_Record is
    Result : Data_Record;
    For Result'Address use Data'Address;
    Pragma Import( Convention => Ada, Entity => Result );
    Pragma Inline( Convert );
begin
    Return Result;
end Convert;

-- Test variables.
Input   : Nyble_Data:= 5;
Output  : Data_Record:= Convert(Input);

-- Display the record.
Procedure Put( Data : In Data_Record ) is
    Use Ada.Text_IO;
begin
    Put_Line( "Read:   "    & ASCII.HT & Boolean'Image(Data.Can_Read) );
    Put_Line( "Write:  "    & ASCII.HT & Boolean'Image(Data.Can_Write) );
    Put_Line( "Archive:"    & ASCII.HT & Boolean'Image(Data.Is_Archived) );
    Put_Line( "System: "    & ASCII.HT & Boolean'Image(Data.Is_System) );
end Put;

@蒂姆·奥列克西:你到底会用
memcpy
做什么?谢谢,但我需要它来帮助ada。对不起,我犯了那个错误。这是我在这里的第一篇文章。这个问题是关于Ada还是C?这个问题是关于Ada的。我从C中得到一个短整数,并将其传递给ada。现在我使用未选中的_转换将短整数转换为记录;这将有助于您获得更好的答案。我删除了C标记,因为它会让一些人困惑地用C给出答案,这是您不想要的。不仅字节顺序不同,结构中位字段的顺序也取决于实现。+1。尽管这不是他要求的,但很可能是他需要做的。@flyx指出Ada通过引用将记录传递给C,除非你告诉它
pragma约定(C\u Pass\u by\u Copy)
。Ada也是,但是你不能对数组应用
C\u Pass\u By\u Copy
,这很烦人。Randy Brukhardt写道:“这就像使用address子句覆盖对象一样——它可能会工作,但它仍然是错误的,而且不能保证新的编译器版本不会破坏这些东西。”
Unchecked\u转换是首选。
Flag_3 : constant Flags := 2#0000_0000_0000_1000#;
Flag_4 : constant Flags := 2 ** 4;
(Get_Flags and Flag_3) /= 0
Type Nyble_Data is mod 2**4;
For Nyble_Data'Size use 4;

Type Data_Record is record
    Can_Read, Can_Write, Is_Archived, Is_System : Boolean:= False;
end record;

-- Ensure 4 bits used.
pragma Pack (Data_Record);
For Data_Record'Size use 4;

-- Specify Layout.
For Data_Record use
    record
        Can_Read    at 0 range 0..0;
        Can_Write   at 0 range 1..1;
        Is_Archived at 0 range 2..2;
        Is_System   at 0 range 3..3;
    end record;

-- This is where the magic occurs.
Function Convert( Data : In Nyble_Data ) Return Data_Record is
    Result : Data_Record;
    For Result'Address use Data'Address;
    Pragma Import( Convention => Ada, Entity => Result );
    Pragma Inline( Convert );
begin
    Return Result;
end Convert;

-- Test variables.
Input   : Nyble_Data:= 5;
Output  : Data_Record:= Convert(Input);

-- Display the record.
Procedure Put( Data : In Data_Record ) is
    Use Ada.Text_IO;
begin
    Put_Line( "Read:   "    & ASCII.HT & Boolean'Image(Data.Can_Read) );
    Put_Line( "Write:  "    & ASCII.HT & Boolean'Image(Data.Can_Write) );
    Put_Line( "Archive:"    & ASCII.HT & Boolean'Image(Data.Is_Archived) );
    Put_Line( "System: "    & ASCII.HT & Boolean'Image(Data.Is_System) );
end Put;