从 int 中剥离位时,编译器会警告一个转换,但不警告其他转换.有解决方法吗?

When stripping bits out of an int, the compiler warns about one conversion but not others. Is there a workaround?

本文关键字:转换 警告 一个 其他 解决 方法 剥离 int 编译器      更新时间:2023-10-16

在下面的代码中,我的编译器抱怨其中一个转换,而不是其他转换。

unsigned ARGB;
unsigned char a( ARGB >> 24 );
unsigned char r( ( ARGB & 0xFF0000 ) >> 16 ); // warning!
unsigned char g( ( ARGB & 0xFF00 ) >> 8 );
unsigned char b( ARGB & 0xFF );

编译器报告"警告 C4244:'正在初始化':从'int'转换为'char',可能丢失数据"......但仅适用于第二次转换。

我想我明白它为什么要这样做了。ab显然是只留下 8 个有效位的单个操作的结果,在g的情况下,按位&产生 16 个有效位(可以存储在short中而不会丢失(,然后结果向右移动,只留下 8 位。但是,相比之下,对r执行的按位&操作会留下一个具有 24 个有效位的中间值,如果要将其存储在某处,则需要int。我猜编译器将移位视为一个单独的进程,作用于整数,这就是为什么它警告可能丢失数据的原因。

由于我们将(几乎所有(警告视为错误,因此我需要解决此问题。显然,我可以使用static_cast来明确记录我想要的内容,但这(在我看来(是一个丑陋的工具,并且表明代码可以写得更好。

有谁知道一种漂亮、整洁、符合标准且可移植的代码形式,可以执行所需的数据转换?

由于可移植性问题,我宁愿不依赖位域。

当交换移位和 AND 的顺序时,警告消失,因此:

unsigned char r( ( ARGB >> 16) & 0xFF );

正如另一个答案中提到的,更改操作可能会有所帮助,但它还有另一个优点:一致性(如果您考虑删除过时的括号,那么,第二个(:

unsigned char a( ARGB >> 24         );
unsigned char r( ARGB >> 16 & 0xffU );
unsigned char g( ARGB >>  8 & 0xffU ); // same value as above
unsigned char b( ARGB       & 0xffU ); //      -- " --

(您也可以在第一行添加掩码,并将 0 移动到最后一行,并希望编译器再次优化它们 - 实际上,它应该对所有掩码都这样做,因为您无论如何都分配给 8 位大小的变量......

现在回到警告(你显然仍然没有摆脱(:显式强制转换现在应该真正强制编译器删除它:

unsigned char x(static_cast<unsigned char>(argb >> y & 0xffU));