Мы компилируем, используя gcc с -Wconversion
включен. Я получаю следующие предупреждения, когда я покидаю результат сдвига, возвращенный isBitSet
функция ниже.
предупреждение: преобразование в ‘u_int16_t {aka short unsigned int}’ из ‘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;
}
Я попытался изменить лямбда ниже, но все равно я получаю ту же ошибку. Как я могу это исправить?
auto isBitSet = [&in](uint8_t position) -> uint16_t {
return (in & (1 << position)) ? 1u:0u;
};
Чтобы избежать предупреждения, вы можете сделать:
signal = uint16_t(signal | isBitSet(1u) << 9);
как operator |
продвигает оператора uint16_t
в int
,
В этом случае оба операторы сдвига а также побитовое включение или оператор применить целочисленные акции к их операндам и с тех пор uint16_t
может быть представлен ИНТ операнды повышены до ИНТ и поэтому gcc
предупреждает вас, что преобразование из большего типа ИНТ в uint16_t может привести к потере.
C ++ способ справиться с этим заключается в использовании static_cast, похоже на следующие работы:
signal = signal | static_cast<uint16_t>(isBitSet(1) << 9);
похоже, что нет необходимости разыгрывать результат |
хотя строго не должно отличаться <<
но я думаю gcc
в состоянии сделать вывод, что в этом случае все в порядке. Технически это лучше:
signal = static_cast<uint16_t>( signal | isBitSet(1) << 9);
Для справки проект стандарта C ++ в 5.8
Операторы смены говорит:
Операнды должны быть целочисленного или незаданного типа перечисления и
интегральные продвижения выполняются. […]
и раздел 5.13
Побитовый оператор ИЛИ говорит:
Обычные арифметические преобразования выполняются; […]
обычные арифметические преобразования в этом случае заканчивается применение целочисленные акции.
Это не ошибка. Это говорит о том, что при преобразовании целого числа в целое число без знака значение изменится, если целое число будет отрицательным. Там действительно нет «исправить» для этого; вам просто нужно быть осторожным, какие значения неподписанный берет из подписанного. Я предполагаю, что вы используете unsigned, потому что он должен быть 0 и выше, поэтому, если что-нибудь, это исправит любые случайно введенные отрицательные значения.