0

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

3 回答 3

2

为避免警告,您可以执行以下操作:

signal = uint16_t(signal | isBitSet(1u) << 9);

asoperator |将运算符提升uint16_tint.

于 2014-10-20T12:14:02.013 回答
2

在这种情况下,移位运算符按位包含或运算符都将整数提升应用于其操作数,并且由于uint16_t可以用int表示,因此操作数被提升为int,因此gcc警告您从较大类型intuint16_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 运算符说:

执行通常的算术转换;[...]

在这种情况下,通常的算术转换最终会应用整数提升

于 2014-10-20T12:25:14.607 回答
-1

这不是错误。它的意思是,通过从整数转换为无符号整数,如果整数为负,值将发生变化。这真的没有“解决办法”。您只需要小心 unsigned 从签名中获取的值。我猜你正在使用无符号,因为它需要为 0 及以上,所以如果有的话,这将修复任何意外输入的负值。

于 2014-10-20T12:13:43.270 回答