0

我有一个需要 4 位的枚举类型,但是当我声明该类型的变量时,编译器会为该变量分配 8 位。

下面是代码的简化版本。

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位的倍数。

4

3 回答 3

1

我不知道任何现代计算机硬件只能为变量分配 4 位。最小值是 8 位字节。

没有冒犯,但我怀疑任何以前版本的 GNAT 也能做到这一点。

现在,在具有关联的代表规范或合适的约定杂注的记录中,AB_Type 类型的单个字段可以仅分配 4 位。

但不能作为离散变量。

于 2013-05-08T18:27:37.397 回答
1

添加到类型中,尤其是添加到记录中。我最近遇到了一个案例,除非附加到类型,否则即使是记录规范子句也不起作用。(也可以使用方面形式。)Pragma Pack( [type_name] );pack

于 2013-05-08T20:04:00.370 回答
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 参考手册中关于地址子句的最后一段,但有两个部分指出,使用覆盖是依赖于实现的(尽管我在 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..

于 2013-05-09T19:29:49.663 回答