我们正在使用启用了-Wconversion
的gcc进行编译。当我离开isBitSet
函数返回的移位结果时,我收到以下警告。
警告:从'int'转换为'u_int16_t {aka short unsigned int}' 可能会改变其值[-Wconversion]
#include <stdint.h>
using namespace std;
void convertToPos(uint16 in) {
auto isBitSet = [&in](uint8_t position) -> bool{
return (in & (1 << position));
};
uint16_t signal = 0;
signal |= isBitSet(1) << 9; // Calibrated
signal |= isBitSet(2) << 10; // Corresponds to digital map
signal |= isBitSet(5) << 13; // DR
signal |= isBitSet(8) << 15; // 3D Fix
}
int main(int argc)
{
convertToPos(4);
return 0;
}
我尝试将lambda改为下面,但我仍然得到同样的错误。我该如何解决?
auto isBitSet = [&in](uint8_t position) -> uint16_t {
return (in & (1 << position)) ? 1u:0u;
};
答案 0 :(得分:2)
为避免此警告,您可以执行以下操作:
signal = uint16_t(signal | isBitSet(1u) << 9);
operator |
将运营商uint16_t
提升为int
。
答案 1 :(得分:2)
在这种情况下,移位运算符和按位包含或运算符将integer promotions应用于其操作数,因为uint16_t
可以由< em> int 操作数被提升为 int ,因此gcc
警告您从较大类型 int 到 uint16_t的转换可能会导致损失。
C ++解决这个问题的方法是使用static_cast,它看起来像下面那样:
signal = signal | static_cast<uint16_t>(isBitSet(1) << 9);
看起来没有必要投出|
的结果,虽然严格来说它应该与<<
没有区别但是我想gcc
能够推断它没关系在这种情况下。从技术上讲,这是更好的:
signal = static_cast<uint16_t>( signal | isBitSet(1) << 9);
作为参考,5.8
Shift运算符中的C ++标准草案说:
操作数应为整数或无范围的枚举类型 整体促销活动。[...]
和部分5.13
按位包含OR运算符表示:
在这种情况下,通常的算术转换最终会应用整数促销。执行通常的算术转换; [...]
答案 2 :(得分:-1)
这不是错误。它的含义是,通过从整数转换为无符号整数,如果整数为负,则值将改变。这真的没有“修复”;你只需要注意unsigned从签名中得到的值。我猜你正在使用unsigned,因为它需要为0及以上,所以如果有的话,这将修复任何意外输入的负值。