抑制未经检查的转换的警告
Suppress warnings for unchecked conversion
我有这段代码:
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
正在运行,但我在编译时收到警告:
warning: types for unchecked conversion have different sizes
warning: size of "Boolean" is 1, size of "T_U8" is 8
warning: source will be extended with 7 high order zero bits
如何抑制这些警告?
可以使用本 Ada Gem blog post 和以下示例中所示的 pragma 来抑制警告:
main.adb
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
为什么在那里需要未经检查的转换?为什么不
function UC_Bool_To_U8 (Value : Boolean) return T_U8
is (Boolean'Pos (Value));
为不同大小的类型创建未经检查的转换是 unsafe/non-portable,所以我认为编译器警告是公平的。我建议您修复代码而不是停用警告。
虽然隐藏警告很容易,但我建议您采用不同的方式。
创建一个相同大小的数字类型,转换为它,然后转换为您需要的类型:
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))
);
我有这段代码:
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
正在运行,但我在编译时收到警告:
warning: types for unchecked conversion have different sizes
warning: size of "Boolean" is 1, size of "T_U8" is 8
warning: source will be extended with 7 high order zero bits
如何抑制这些警告?
可以使用本 Ada Gem blog post 和以下示例中所示的 pragma 来抑制警告:
main.adb
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
为什么在那里需要未经检查的转换?为什么不
function UC_Bool_To_U8 (Value : Boolean) return T_U8
is (Boolean'Pos (Value));
为不同大小的类型创建未经检查的转换是 unsafe/non-portable,所以我认为编译器警告是公平的。我建议您修复代码而不是停用警告。
虽然隐藏警告很容易,但我建议您采用不同的方式。
创建一个相同大小的数字类型,转换为它,然后转换为您需要的类型:
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))
);