编译器警告转换

时间:2014-10-20 12:05:01

标签: c++ gcc compiler-warnings integer-promotion

我们正在使用启用了-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;
};

3 个答案:

答案 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及以上,所以如果有的话,这将修复任何意外输入的负值。