2013-05-08 39 views
0

我有一个枚举类型需要4位,但是当我声明该类型的变量时,编译器将该变量分配给8位。强制Ada使用枚举类型的最小规格大小与gnat 4.4

下面是代码的简化版本。

subtype ab_range_index is word range 0..3; 
type ab_buffer_type is array(ab_range_index) of bit; 

type Buffer is record 
    ... 
    var1  : some_buffer_type; 
    Orig_AB_var : ab_buffer_type; 
    ... 
end record; 
for Buffer use record 
    ... 
    var1   at 16 range 0..5; 
    Orig_AB_var at 16 range 6..9; 
    ... 
end record; 
... 
type AB_type is (A,B); 
for AB_type use (A => 0, B => 5); 
for AB_type'Size use 4; 
... 
procedure Proc(AB_buff : ab_buffer_type) is 
AB_var : AB_type;      -- AB_var'Size returns 8 in debugger. 
for AB_var use at AB_buff'Address; 
begin 
    data_valid = AB_var'valid;   -- returns false since the variable 
             -- contains extra bits 
    ...  

这一切都在以前的gnat版本下工作,但不在gnat 4.4.6下。我知道gnat符合Ada规范。

有没有办法强制编译器在上面的例子中使AB_var为4位? 我试过'Object_Size,但它需要是8位的倍数。

+0

您是否尝试过设置“对象大小(AB_var)”而不仅仅是类型? – egilhh 2013-05-08 18:19:21

+0

我得到以下编译错误:“原始对象的大小必须是2的范围8-64的幂”谢谢你的想法。 – user1998752 2013-05-08 19:00:12

+0

@ user1998752:这是有道理的,因为只能分配一定数量的架构可寻址字节/位,即1/8,2/16,4/32或8/64 – 2013-05-08 19:48:24

回答

1

我不知道任何可以为变量分配4位的现代计算机硬件。最小值将是一个8位字节。

并没有冒犯,但我怀疑任何先前的GNAT版本都可以做到。

现在在具有相关联的规范或合适的约定编译指示的记录中,类型AB_Type的单个字段可以仅分配4位。

但不作为离散变量。

+0

我知道我可以在gnat 4.1.2上编译相同的代码并获得所需的结果。我将不得不检查差异是否确实是AB_var或其他的大小。你的记录想法也可以使用。谢谢! – user1998752 2013-05-08 19:04:43

+0

Marc - 你是对的,在先前的gnat版本下,AB_var是8位。但是,当变量分配了“for AB_var use at AB_buff'Address;”时声明只使用或评估了所需的4位。任何关于那里发生了什么的想法,为什么它改变了新的gnat版本或如何让它像以前一样工作? – user1998752 2013-05-08 20:40:46

+0

我不知道可能发生了什么变化(我以前从未做过这样的事情)。有些事情我会尝试:1)确保地址子句引用数组的开始,即在AB_buff(AB_buff'First)'地址处使用AB_var; 2)尝试编译指示约定(C,AB_Var),理由是告诉编译器只保留该变量。 – 2013-05-08 20:55:11

1

添加Pragma Pack([type_name]);的类型,尤其是备案。我最近有一个案例,即使一个记录规范条款不起作用,除非pack被附加到该类型。 (也可以使用外观形式。)

+0

这不会让他变成一个4位变量。 – 2013-05-08 20:05:18

+0

Pragma包仅适用于阵列或记录。不管怎么说,多谢拉。 – user1998752 2013-05-08 20:20:18

+0

是的,我必须将其应用于记录才能接受rep条款。奇怪的事情,那。 – Shark8 2013-05-08 21:29:15

1

对于发布可编辑的播放器,几乎总是有些话要说。我不知道你的代码是什么真的很喜欢,但这个工程只是GCC 4.8.0罚款:

with Ada.Text_IO; use Ada.Text_IO; 
procedure Small_Parameter_Conversion is 
    type M_N_Type is (M, N); 
    for M_N_Type use (M => 0, N => 5); 
    for M_N_Type'Size use 4; 
    type Fill is array (Positive range <>) of Boolean; 
    for Fill'Component_Size use 1; 
    type Import is record 
     M_N : M_N_Type; 
     Filler : Fill (1 .. 4); 
    end record; 
    for Import use record 
     M_N at 0 range 0 .. 3; 
     Filler at 0 range 4 .. 7; 
    end record; 
    type A_B_Type is (A, B); 
    for A_B_Type use (A => 0, B => 5); 
    for A_B_Type'Size use 4; 
    procedure Proc (Input : M_N_Type) is 
     A_B : A_B_Type; 
     for A_B'Address use Input'Address; 
    begin 
     if not A_B'Valid then 
     Put_Line ("invalid."); 
     else 
     Put_Line (A_B'Img); 
     end if; 
    end Proc; 
    V : Import; 
begin 
    V := (M_N => M, Filler => (others => True)); 
    Proc (V.M_N); 
    V := (M_N => N, Filler => (others => True)); 
    Proc (V.M_N); 
end Small_Parameter_Conversion; 

也就是说,Unchecked_Conversion是更好的路要走。最后一段,但GNAT Reference Manual section on Address Clauses中的两个指出使用重叠是依赖于实现的(尽管我无法在RM中找到它说的地方)。如果M_N_Type实际上定义为

type M_N_Type is (M, N, O); 
for M_N_Type use (M => 0, N => 5, O => 6); 

Proc被称为

V := (M_N => O, Filler => (others => True)); 
Proc (V.M_N); 

然后,果然,它打印invalid.出错

一个可能的路线会。

+0

我尝试了上面的示例代码,并确定它的工作。数据从文件中填充,这可能是您的第二个示例中问题的原因。我试图在一个小的可编译程序中复制错误,但不认为这是一个很好的使用努力。谢谢您的帮助! – user1998752 2013-05-16 15:47:01

+0

你愿意提高我的答案(甚至接受它)吗? – 2013-05-16 18:21:37