【问题标题】:Ada Endianness Float/IntegerAda Endianness 浮点数/整数
【发布时间】:2018-10-09 09:04:40
【问题描述】:

我是 Ada 的新开发人员,如果我不够清楚,请原谅我。 我遇到了一个问题,我不知道故障从何而来。我首先解释一下上下文: 我拥有一组适用于 qemu (BE) 的测试。我希望使用编译指示 Default_Scalar_Storage_Order (High_Order_First) 在 PC 本机 (x86) 上执行它们。我注意到我的一些测试运行良好,但包括浮动在内的测试并非如此。为了简单起见,我编写了一个包含 FLOAT 和 INT 的测试。

with AUNIT.ASSERTIONS; use AUNIT.ASSERTIONS;
with BASIC_TYPES;
with BASIC_TYPES.STREAM;
with INTERFACES;
with ADA.INTEGER_TEXT_IO;
with ADA.FLOAT_TEXT_IO;
with ADA.TEXT_IO;
with STREAMS;
with SYSTEM;

package body TEST.TEST is

   function Integer2Hexa(Hex_Int : Integer; Bits_Nbr : Integer) return String is
   Hexa : String(1..Bits_Nbr);
   begin
      Ada.Integer_Text_IO.Put(Hexa,Hex_Int,16);
      return Hexa;
   end Integer2Hexa;

   function NAME (T : TEST) return AUNIT.MESSAGE_STRING is
      pragma UNREFERENCED (T);
   begin
      return AUNIT.FORMAT ("Test package");
   end NAME;

   IntegerNbr : BASIC_TYPES.INT32_T;
   FloatNbr : INTERFACES.IEEE_Float_32;

   procedure RUN_TEST (T : in out TEST) is

      PACKED_ARRAY : BASIC_TYPES.UINT8_ARRAY_NC_T (1 .. 8) := (others => 0);
      MY_STREAM    : STREAMS.STREAM_T;

      use type BASIC_TYPES.UINT8_ARRAY_NC_T;

   begin

      IntegerNbr := 479037433;
      FloatNbr := 2.0012151e+09;

      ADA.TEXT_IO.PUT_LINE ("Default bit order: " & SYSTEM.Default_Bit_Order'IMG);

      ADA.TEXT_IO.PUT_LINE ("Integer size : " & INTEGER'IMAGE (INTEGER'SIZE));

      ADA.TEXT_IO.PUT ("16#4EEE903D#"); -- 2.0012151e+09 in FLOAT BIG ENDIAN
      ADA.TEXT_IO.PUT (Integer2Hexa(Integer(IntegerNbr),32)); -- 16#1C8D87F9# in INT BIG ENDIAN
      ADA.TEXT_IO.NEW_LINE;

      -- Init the stream
      STREAMS.INIT (MY_STREAM      => MY_STREAM,
                    STREAM_ADDRESS => PACKED_ARRAY (PACKED_ARRAY'FIRST)'ADDRESS,
                    STREAM_SIZE    => PACKED_ARRAY'LENGTH);

      BASIC_TYPES.STREAM.WRITE_FLOAT_T (MY_STREAM  => MY_STREAM,
                                      ITEM       => FloatNbr,
                                      ALIGN_MODE => STREAMS.PACK);

      BASIC_TYPES.STREAM.WRITE_INT32_T (MY_STREAM  => MY_STREAM,
                                      ITEM       => IntegerNbr,
                                      ALIGN_MODE => STREAMS.PACK);


      if (not ASSERT(PACKED_ARRAY = (16#4e#,  16#ee#,  16#90#,  16#3d#,  16#1c#,  16#8d#,  16#87#,  16#f9#), "PACKED_ARRAY incorrect")) then
         for I in PACKED_ARRAY'RANGE loop
            ADA.TEXT_IO.PUT (Integer2Hexa(Integer(PACKED_ARRAY (I)),8));
         end loop;
         ADA.TEXT_IO.NEW_LINE;

      end if;

   end RUN_TEST;

end TEST.TEST;

我注意到 INT 的写入是正确的,但 FLOAT 的情况并非如此(它是用 Little Endian 编写的)。确实在退出时我应该有

16#4e#, 16#ee#, 16#90#, 16#3d#, 16#1c#, 16#8d#, 16#87#, 16#f9#

但我明白了

16#3d#, 16#90#, 16#ee#, 16#4e#, 16#1c#, 16#8d#, 16#87#, 16#f9#

我使用这个网站来确认我的结果:https://www.scadacore.com/tools/programming-calculators/online-hex-converter/

我不知道由于 pragma 的转换是否正确用于 FLOAT。我在包 Compiler 的 gpr 文件中调用它,并在 PRAGMA.txt 中使用此文本:pragma Default_Scalar_Storage_Order(High_Order_First);

   package Compiler is
      for Local_Configuration_Pragmas use "PRAGMAS.txt";
      for Switches ("ada") use ("-g");
   end Compiler;

问题是否出现在我使用 pragma 的方式上?

这里是调用的过程:

       procedure WRITE_FLOAT_T
         (MY_STREAM  : in out STREAMS.STREAM_T;
          ITEM       : in BASIC_TYPES.FLOAT_T;
          ALIGN_MODE : in STREAMS.ALIGN_MODE_T)
       is

          pragma UNREFERENCED (ALIGN_MODE);

          -- Temporary types for non pack case
          type TMP_TYPE_T is new STANDARD.FLOAT;
          for TMP_TYPE_T'VALUE_SIZE use FLOAT_T_SIZE_C;
          TMP_TYPE : TMP_TYPE_T;
          subtype BITS_FIELD_T is STREAMS.BIT_FIELD_ARR_NC_T (1 .. STREAMS.SIZE_T (FLOAT_T_SIZE_C));

          function TO_BITS_ARRAY is new UNCHECKED_CONVERSION (TMP_TYPE_T,
                                                              BITS_FIELD_T);


       begin

          -- Convert item to a temporary type
          TMP_TYPE := TMP_TYPE_T(ITEM);
          STREAMS.WRITE (MY_STREAM  => MY_STREAM,
                         DATA       => TO_BITS_ARRAY(TMP_TYPE));

       end WRITE_FLOAT_T;

   procedure WRITE (MY_STREAM : in out STREAM_T;
                    DATA      : in BIT_FIELD_ARR_NC_T) is

   begin

      if (MY_STREAM.ERROR_CODE = NO_ERROR)
        and then (MY_STREAM.WRITE_OFFSET + DATA'LENGTH - 1 <= MY_STREAM.STREAM_SIZE * 8) then

         if (MY_STREAM.WRITE_OFFSET mod 8 = 1) and then (DATA'LENGTH mod 8 = 0) then

            -- Byte mode
            WRITE_BYTES(MY_STREAM => MY_STREAM,
                        DATA      => DATA);

         else

            -- Bit mode
            WRITE_BITS(MY_STREAM => MY_STREAM,
                       DATA      => DATA);

         end if;

      elsif (MY_STREAM.ERROR_CODE = NO_ERROR) then

         -- Update ERROR_CODE on first error
         MY_STREAM.ERROR_CODE := END_ERROR;

      end if;

   end WRITE;

   procedure WRITE_BYTES (MY_STREAM : in out STREAM_T;
                          DATA      : in BIT_FIELD_ARR_NC_T) is

      BYTE_FIELD_ARR : BYTE_FIELD_ARR_NC_T (1 .. MY_STREAM.STREAM_SIZE);
      for BYTE_FIELD_ARR'ADDRESS use MY_STREAM.STREAM_ADDRESS;

      TMP_BYTE_FIELD_ARR : BYTE_FIELD_ARR_NC_T (1 .. DATA'LENGTH / 8);
      for TMP_BYTE_FIELD_ARR'ADDRESS use DATA'ADDRESS;

   begin

      -- Write byte field
      BYTE_FIELD_ARR ((MY_STREAM.WRITE_OFFSET + 7) / 8 .. (MY_STREAM.WRITE_OFFSET + 7) / 8 + (DATA'LENGTH / 8) - 1) := TMP_BYTE_FIELD_ARR;
      MY_STREAM.WRITE_OFFSET := MY_STREAM.WRITE_OFFSET + DATA'LENGTH;

   end WRITE_BYTES;

提前谢谢你!

Q.Dherb

【问题讨论】:

    标签: endianness ada


    【解决方案1】:

    根据Scalar_Storage_Order的文档:

    此实现定义的属性仅适用于 Array 和 Record。这意味着它对浮点或整数等标量类型的内存布局没有影响。无论 Default_Scalar_Storage_Order 属性的值如何,在大端机器上,16#12345678# 整数将表示为 12 34 56 78,而在低端机器上,它将表示为 78 56 34 12。

    对于数组,它决定了每个标量组件的 storage_element(通常是字节)的顺序。在您的情况下,所有数组组件的大小都小于或等于存储元素,这意味着 Scalar_Storage_Order 子句无效。

    下面是一个例子,展示了这个子句对数组的影响:

    with Ada.Text_IO;
    with System;
    with Interfaces;
    with Ada.Streams;
    with Ada.Integer_Text_IO;
    
    procedure Scalar_Storage_Element_Exemple is
    
       type T_U16_Arr_Le is array (Positive range <>) of Interfaces.Unsigned_16
         with Component_Size => 16, Scalar_Storage_Order => System.Low_Order_First;
       type T_U16_Arr_Be is array (Positive range <>) of Interfaces.Unsigned_16
         with Component_Size => 16, Scalar_Storage_Order => System.High_Order_First;
    
       type T_U8_Arr_Le is array (Positive range <>) of Interfaces.Unsigned_8
         with Component_Size => 8, Scalar_Storage_Order => System.Low_Order_First;
       type T_U8_Arr_Be is array (Positive range <>) of Interfaces.Unsigned_8
         with Component_Size => 8, Scalar_Storage_Order => System.High_Order_First;
    
       Arr_16_LE : T_U16_Arr_Le (1 .. 2) := (16#1234#, 16#5678#);
       Arr_16_BE : T_U16_Arr_Be (1 .. 2) := (16#1234#, 16#5678#);
    
       Arr_8_LE : T_U8_Arr_Le (1 .. 4) := (16#12#, 16#34#, 16#56#, 16#78#);
       Arr_8_BE : T_U8_Arr_Be (1 .. 4) := (16#12#, 16#34#, 16#56#, 16#78#);
    
       Sea_16_LE : Ada.Streams.Stream_Element_Array (1 .. 4) with Address => Arr_16_LE'Address;
       Sea_16_BE : Ada.Streams.Stream_Element_Array (1 .. 4) with Address => Arr_16_BE'Address;
    
       Sea_8_LE : Ada.Streams.Stream_Element_Array (1 .. 4) with Address => Arr_8_LE'Address;
       Sea_8_BE : Ada.Streams.Stream_Element_Array (1 .. 4) with Address => Arr_8_BE'Address;
    
       function byte2Hexa(byte : Integer) return String is
          Hexa : String(1..8);
       begin
          Ada.Integer_Text_IO.Put(Hexa,byte,16);
          return Hexa;
       end byte2Hexa;
    
    begin
    
       for byte of Sea_16_LE loop
          Ada.Text_IO.Put(byte2Hexa(Integer(byte)));
       end loop;
       -- display 16#34#  16#12#  16#78#  16#56#
       -- each item of the array is in LE
    
       Ada.Text_IO.New_Line;
    
       for byte of Sea_16_BE loop
          Ada.Text_IO.Put(byte2Hexa(Integer(byte)));
       end loop;
       -- 16#12#  16#34#  16#56#  16#78#
       -- each item of the array is in BE
    
       Ada.Text_IO.New_Line;
    
       for byte of Sea_8_LE loop
          Ada.Text_IO.Put(byte2Hexa(Integer(byte)));
       end loop;
       -- 16#12#  16#34#  16#56#  16#78#
       -- no effect as size of component is inferior or equal to storage_element size
    
       Ada.Text_IO.New_Line;
    
       for byte of Sea_8_BE loop
          Ada.Text_IO.Put(byte2Hexa(Integer(byte)));
       end loop;
       -- 16#12#  16#34#  16#56#  16#78#
       -- no effect as size of component is inferior or equal to storage_element size
    
    end Scalar_Storage_Element_Exemple;
    

    您的浮点序列化可以在您的 QEMU 上运行,因为您已经在 BE 上。因此 Scalar_Storage_Order 只是确认,没有任何作用。

    它不适用于 x86,因为本机字节序是 LE,并且如前所述,BE Scalar_Storage_Order 子句对所涉及的类型没有影响。所以最终结果是一个 LE 浮点数。

    如果您使用相同的序列化逻辑(未提供相关代码,因此我假设它不同),Integer 或 Float 应该在此处表现类似。

    【讨论】:

    • 谢谢,这会很有用!
    • 您可以更正您的答案:由于未知原因(Default_Scalar_Storage_Order 行为),如果输入类型为整数,则会发生字节交换,但当输入为浮点数时则不会。
    【解决方案2】:

    这并不完全清楚,因为您包含了很多令人困惑的细节,但我认为您正在尝试以独立于字节序的方式写入流以进行通信(通过net?) 不同字节序的机器之间。

    您的过程WRITE_FLOAT_T 的问题在于它的ITEM 是一个普通的浮点数,所以Scalar_Storage_Order 无效。

    The way I've used Scalar_Storage_Order是声明我要发送的记录,

    type SNTP_Packet is record
       -- contents
    end record
      with
        Bit_Order => System.High_Order_First,
        Scalar_Storage_Order => System.High_Order_First,
        Size => 48 * 8;
    for SNTP_Packet use record
       -- placement of content
    end record;
    
    subtype Net_Packet is Ada.Streams.Stream_Element_Array (1 .. 48);
    --  This is what actually gets streamed
    
    function To_Net_Packet
    is new Ada.Unchecked_Conversion (SNTP_Packet, Net_Packet);
    function To_SNTP_Packet
    is new Ada.Unchecked_Conversion (Net_Packet, SNTP_Packet);
    

    您可以使用pragma Default_Scalar_Storage_Order,但我不确定是否需要使Bit_Order 匹配。

    或者,如果您希望能够使用例如Float'Write,您可以更改 GNAT 流式传输基本类型的方式。

    Ada 运行时使用包 System.Stream_Attributes 在文件 s-stratt.adss-stratt.adb 中处理基本类型的流式传输,并在 s-stratt__xdr.adb 中提供替代实现(在最新的编译器中;旧的编译器可能使用不同的文件名字,但里面会有一个xdr)。

    让编译器使用这个替代版本并不是很简单,但这对我有用:

    1. s-stratt__xdr.adb复制到工作目录中的s-stratt.adb

    2. 使用gnatmake -a 在本地编译运行时的必要部分(-gnatpg 表示“为运行时编译”):

      gnatmake -a -f s-stratt.adb -gnatpg

    3. 构建你的程序:

      gprbuild main.adb

    注意,gprbuild 不支持 -a。可以使用项目文件来创建包含修改后的运行时组件的库。

    【讨论】:

      【解决方案3】:

      您正在尝试独立于您的热字节序以 bigendian 编码数据(可能用于网络传输)。 您希望 UNCHECKED_CONVERSION 的两个参数都是 Scalar_Storage_Order=System.High_Order_First 定义的 here

      如果指定了相反的存储顺序,则每当读取类型 S 对象的标量组件的值时,首先反转封闭机器标量的存储元素。

      您的问题来自使用旧的 gcc 版本。

      我尝试通过测试将 FLOAT_T.Scalar_Storage_OrderSystem.Default_Bit_Order 转换为 System.High_Order_First 来分解问题,感谢 UNCHECKED_CONVERSION 使用以下代码:

      inc.ads:

      with SYSTEM;
      
      package inc is
      
          type BITS32_T is mod (2 ** 32);
          for BITS32_T'SIZE use 32;
          
          subtype UINT32_T is BITS32_T;
          subtype INT32_UNSIGNED_T is UINT32_T;
      
          type SIZE_T is new UINT32_T;
      
          subtype INDEX_T is SIZE_T range 1 .. SIZE_T'LAST;
      
          type BIT_T is mod (2 ** 1);
          for BIT_T'SIZE use 1;
          
          type BITS8_T is mod (2 ** 8);
          for BITS8_T'SIZE use 8;
      
          -- 64-bit signed integer
          type INT64_T is range -(2 ** (64 - 1)) .. (2 ** (64 - 1) - 1);
          for INT64_T'SIZE use 64;
          subtype INT64_SIGNED_T is INT64_T;
      
          type BIT_FIELD_ARR_NC_T is array (INDEX_T range <>) of BIT_T;
          for BIT_FIELD_ARR_NC_T'COMPONENT_SIZE use 1;
          for BIT_FIELD_ARR_NC_T'Scalar_Storage_Order use System.High_Order_First;
      
      --Low_Order_First
          type BYTE_FIELD_ARR_HOST_ENDIANNESS_NC_T is array (INDEX_T range <>) of BITS8_T;
          for BYTE_FIELD_ARR_HOST_ENDIANNESS_NC_T'COMPONENT_SIZE use 8;
          
          type BIT_FIELD_ARR_HOST_ENDIANNESS_NC_T is array (INDEX_T range <>) of BIT_T;
          for BIT_FIELD_ARR_HOST_ENDIANNESS_NC_T'COMPONENT_SIZE use 1;
      
      end inc;
      

      test_types.adb:

      with inc;
      with INTERFACES;
      with Ada.Text_IO;
      with Ada.Integer_Text_IO;
      with UNCHECKED_CONVERSION;
      
      procedure TEST_TYPES  is
          
          longfloat : INTERFACES.IEEE_FLOAT_64 := INTERFACES.IEEE_FLOAT_64(1e11);
          
          --float64 : inc.INT64_T := 16#1122334455667788#;
          int64 : inc.INT64_T := 16#1122334455667788#;
          
          
          ---------------- TYPE used to print represnentation in memory ------------------------------
          
          subtype BYTES_ARRAY_T is inc.BYTE_FIELD_ARR_HOST_ENDIANNESS_NC_T (1 .. 8);
      
          -------- tableau de bits -------
          subtype BITS_FIELD_T is inc.BIT_FIELD_ARR_NC_T (1 .. 64);
          subtype BITS_FIELD_HOST_ENDIANNESS_T is inc.BIT_FIELD_ARR_HOST_ENDIANNESS_NC_T (1 .. 64);
      
      
          
          ---------------- FLOAT with BIG ENDIAN encoding ------------------------------
          type TMP_TYPE_T is new STANDARD.LONG_FLOAT;
              for TMP_TYPE_T'VALUE_SIZE use 64;
              TMP_TYPE : TMP_TYPE_T;
          function TO_BYTES_ARRAY is new UNCHECKED_CONVERSION (TMP_TYPE_T, BITS_FIELD_T);
          bytes: BITS_FIELD_T;
          ---------------- FLOAT with host ENDIANNESS ------------------------------
          function TO_BYTES_HOST_ENDIANNESS_ARRAY is new UNCHECKED_CONVERSION (TMP_TYPE_T, BITS_FIELD_HOST_ENDIANNESS_T);
          bytesNoEndian: BITS_FIELD_HOST_ENDIANNESS_T;
      
      
      
          ---------------- INTEGER with ENDIAN CONVERSION ------------------------------
          type TMP_Integer_T is new STANDARD.LONG_LONG_INTEGER;
              for TMP_Integer_T'VALUE_SIZE use 64;
              TMP_Integer : TMP_Integer_T; 
          function TO_BYTES_ARRAY_Integer is new UNCHECKED_CONVERSION (TMP_Integer_T, BITS_FIELD_T);
          bytes_integer: BITS_FIELD_T;    
          ---------------- INTEGER without ENDIAN CONVERSION ------------------------------
          function TO_BYTES_ARRAY_HOST_ENDIANNESS_Integer is new UNCHECKED_CONVERSION (TMP_Integer_T, BITS_FIELD_HOST_ENDIANNESS_T);
          bytes_no_endian_integer: BITS_FIELD_HOST_ENDIANNESS_T;      
      
          -- representation in memory
          float_rep: BYTES_ARRAY_T;
          float_bits_field_rep: BYTES_ARRAY_T;
          int_rep: BYTES_ARRAY_T;
          int_bits_field_rep: BYTES_ARRAY_T;
      
          for float_rep'ADDRESS use bytesNoEndian'ADDRESS;
          for float_bits_field_rep'ADDRESS use bytes'ADDRESS;
          for int_rep'ADDRESS use bytes_no_endian_integer'ADDRESS;
          for int_bits_field_rep'ADDRESS use bytes_integer'ADDRESS;
      ------------------ FUNCTION FROM STACKOVERFLOW-----------------------
          function byte2hexa(byte : Integer) return String is
              Hexa : String(1..8);
          begin
              Ada.Integer_Text_IO.Put(Hexa, byte, 16);
              return Hexa;
          end byte2hexa;  
          procedure array2hexa(bytes : BYTES_ARRAY_T)  is
          begin
              Ada.Integer_Text_IO.Put(Integer(bytes(1)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(2)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(3)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(4)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(5)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(6)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(7)), Base => 16);
              Ada.Integer_Text_IO.Put(Integer(bytes(8)), Base => 16);
              Ada.Text_IO.New_line;
          end array2hexa; 
      begin
          -- test serialisation on float 
          TMP_TYPE := TMP_TYPE_T(longfloat);
          bytesNoEndian := TO_BYTES_HOST_ENDIANNESS_ARRAY(TMP_TYPE);
          Ada.Text_IO.Put_line("float in native endianess ");
          array2hexa(float_rep);
          Ada.Text_IO.New_line;
          
          
          Ada.Text_IO.Put_line("float into BigEndian Bit array");
          TMP_TYPE := TMP_TYPE_T(longfloat);
          bytes := TO_BYTES_ARRAY(TMP_TYPE);
          array2hexa(float_bits_field_rep);
          Ada.Text_IO.New_line;
          
          -- test serialisation on integer 
          TMP_Integer := TMP_Integer_T(int64); 
          bytes_no_endian_integer := TO_BYTES_ARRAY_HOST_ENDIANNESS_Integer(TMP_Integer);
          Ada.Text_IO.Put_line("Integer in native endianess ");
          array2hexa(int_rep);
      
          Ada.Text_IO.New_line;
          Ada.Text_IO.Put_line("Integer into BigEndian Bit array");
          TMP_Integer := TMP_Integer_T(int64); 
          bytes_integer := TO_BYTES_ARRAY_Integer(TMP_Integer);
          array2hexa(int_bits_field_rep);
          
      end TEST_TYPES;
      

      在我提出的代码中,问题来自于 BITS_FIELD_T'element 的字节序已明确定义,但 UNCHECKED_CONVERSION 的行为未定义(关于从浮点字节序到 BITS_FIELD_T 字节序的转换)

      令人惊讶的是,使用 gcc (GCC) 6.2.1 20161010(适用于 GNAT Pro 17.2 20170606) UNCHECKED_CONVERSION 转换整数的字节序而不是浮点数:

      float in native endianess
            16#0#      16#0#      16#0#     16#E8#     16#76#     16#48#     16#37#     16#42#
      
      float into BigEndian Bit array
            16#0#      16#0#      16#0#     16#E8#     16#76#     16#48#     16#37#     16#42#
      
      Integer in native endianess
           16#88#     16#77#     16#66#     16#55#     16#44#     16#33#     16#22#     16#11#
      
      Integer into BigEndian Bit array
           16#11#     16#22#     16#33#     16#44#     16#55#     16#66#     16#77#     16#88#
      

      但使用 gcc (GCC) 7.3.1 20181018(适用于 GNAT Pro 20.0w 20181017) 浮点值被正确交换:

      float in native endianess
            16#0#      16#0#      16#0#     16#E8#     16#76#     16#48#     16#37#     16#42#
      
      float into BigEndian Bit array
           16#42#     16#37#     16#48#     16#76#     16#E8#      16#0#      16#0#      16#0#
      

      一种解决方案(对于旧编译器)是在UNCHECKED_CONVERSION 之前通过一个中间BigEndian 结构:


      procedure WRITE_LONG_FLOAT_T
           (MY_STREAM  : in out STREAMS.STREAM_T;
            ITEM       : in BASIC_TYPES.LONG_FLOAT_T;
            ALIGN_MODE : in STREAMS.ALIGN_MODE_T)
         is
         
            pragma UNREFERENCED (ALIGN_MODE);
      
            -- Temporary types for non pack case
            type TMP_TYPE_T is new STANDARD.LONG_FLOAT;
            for TMP_TYPE_T'VALUE_SIZE use LONG_FLOAT_T_SIZE_C;
            TMP_TYPE : TMP_TYPE_T;
            subtype BITS_FIELD_T is STREAMS.BIT_FIELD_ARR_NC_T (1 .. STREAMS.SIZE_T (LONG_FLOAT_T_SIZE_C));
      
            function TO_BITS_ARRAY is new UNCHECKED_CONVERSION (TMP_TYPE_T,
                                                                BITS_FIELD_T);
      
            type ITEM_ENDIAN_T is
               record
                  TMP_TYPE_ENDIAN : TMP_TYPE_T;
               end record;
            for ITEM_ENDIAN_T'Bit_Order use System.High_Order_First;
            for ITEM_ENDIAN_T'Scalar_Storage_Order use System.High_Order_First;
            ITEM_ENDIAN : ITEM_ENDIAN_T;
      
            --subtype LONG_FLOAT_TO_ARRAY_T is PUS.TYPES.BYTE_FIELD_NC_T (1 .. 8);
            function TO_BITS_ARRAY_ENDIAN is new UNCHECKED_CONVERSION (ITEM_ENDIAN_T, BITS_FIELD_T);
      
         begin
         
            
            -- Convert item to a temporary type
            TMP_TYPE := TMP_TYPE_T(ITEM);
            ITEM_ENDIAN.TMP_TYPE_ENDIAN := TMP_TYPE;
      
      
            STREAMS.WRITE (MY_STREAM  => MY_STREAM,
                           --DATA       => TO_BITS_ARRAY(TMP_TYPE));
                           DATA       => TO_BITS_ARRAY_`enter code here`ENDIAN(ITEM_ENDIAN));
         
         end WRITE_LONG_FLOAT_T;
      

      【讨论】:

        【解决方案4】:

        一种方法(或另一种想法来源......)是使用 IEEE 754 表示包:http://www.dmitry-kazakov.de/ada/components.htm#IEEE_754

        这些包的字节序中立使用在这里完成:http://excel-writer.sf.net/

        【讨论】:

          猜你喜欢
          • 2011-01-04
          • 1970-01-01
          • 2017-07-26
          • 2020-07-26
          • 2011-01-10
          • 2016-11-06
          • 1970-01-01
          • 2013-09-14
          • 2013-06-12
          相关资源
          最近更新 更多