3

我有这段代码:

with Ada.Unchecked
private package MyPackage is
    function UC_Bool_To_U8 is new Ada.Unchecked_Conversion (Source => Boolean, Target => T_U8);
end MyPackage;

其中 T_U8 是:

type T_U8 is range 0 .. 2**7;

功能UC_Bool_To_U8 正在运行,但我在编译时出现警告:

警告:未经检查的转换类型具有不同的大小

警告:“布尔”的大小为 1,“T_U8”的大小为 8

警告:源将扩展 7 个高位零位

我怎样才能抑制这些警告?

4

3 回答 3

6

可以使用此Ada Gem 博客文章和以下示例中所示的编译指示来抑制警告:

主文件

with Ada.Unchecked_Conversion;

procedure Main is

   --  Using a modular type instead of an integer type. Result is the same.
   type T_U8 is mod 2**7;    
   
   pragma Warnings (Off, "types for unchecked conversion have different sizes");   
   
   function UC_Bool_To_U8 is new Ada.Unchecked_Conversion
     (Source => Boolean, Target => T_U8);
   
   pragma Warnings (On, "types for unchecked conversion have different sizes");
   
begin
   null;
end Main;

但是,也请考虑Unchecked_Conversion在将布尔类型转换为某些整数或模块化类型时不要使用。编译器将完全优化一个简单的if语句,如Compiler Explorer所示:

编译器资源管理器的输入

pragma Source_File_Name (To_U8, Body_File_Name => "example.adb");

with Interfaces.C.Extensions;

function To_U8 (B : Boolean) return Interfaces.C.Extensions.Unsigned_8 with Inline is
begin
    return (if B then 1 else 0);
end To_U8;

Compiler Explorer 的输出(使用编译器开关-O1-O2

_ada_to_u8:
        mov     eax, edi  # b, tmp86
        ret  
于 2021-08-10T11:10:19.097 回答
5

为什么你需要未经检查的转换?为什么不

   function UC_Bool_To_U8 (Value : Boolean) return T_U8
     is (Boolean'Pos (Value));

为不同大小的类型创建未经检查的转换是不安全/不可移植的,所以我认为编译器警告是公平的。我建议您修复代码而不是停用警告。

于 2021-08-11T08:55:18.877 回答
0

虽然隐藏警告很容易,但我建议您采用不同的方式。

创建一个大小相同的数值类型,转换成它,然后转换成你需要的类型:

type T_U1 is range 0 .. 1 with Size => 1;
function UC_Bool_To_U1 (Value : Boolean) return T_U1 is new Ada.Unchecked_Conversion
 (Source => Boolean, Target => T_U1);
function UC_Bool_To_U8 (Value : Boolean) return T_U8 is (
    T_U8 (UC_Bool_To_U1 (Value))
);
于 2021-08-13T09:58:47.163 回答