Reputation: 9259
We are compiling using gcc with -Wconversion
enabled. I get following warnings when I left shift result returned by isBitSet
function below.
warning: conversion to 'u_int16_t {aka short unsigned int}' from 'int' may alter its value [-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;
}
I tried changing lambda to below, but still I get the same error. How can I fix it?
auto isBitSet = [&in](uint8_t position) -> uint16_t {
return (in & (1 << position)) ? 1u:0u;
};
Upvotes: 0
Views: 1478
Reputation: 158449
In this case both shift operators and bitwise inclusive or operator apply the integer promotions to their operands and since uint16_t
can be represented by int the operands are promoted to int and therefore gcc
is warning you that the conversion from a larger type int to uint16_t may result in loss.
The C++ way to deal with this is to use static_cast, it looks like the following works:
signal = signal | static_cast<uint16_t>(isBitSet(1) << 9);
it looks like it is not neccessary to cast the result of |
, although strictly it should be no different than <<
but I guess gcc
is able to deduce that it is okay in this case. Technically this is better:
signal = static_cast<uint16_t>( signal | isBitSet(1) << 9);
For reference the draft C++ standard in 5.8
Shift operators says:
The operands shall be of integral or unscoped enumeration type and integral promotions are performed.[...]
and section 5.13
Bitwise inclusive OR operator says:
The usual arithmetic conversions are performed;[...]
the usual arithmetic conversions in this case ends up applying the integer promotions.
Upvotes: 2
Reputation: 217065
To avoid the warning, you may do:
signal = uint16_t(signal | isBitSet(1u) << 9);
as operator |
promotes operator uint16_t
to int
.
Upvotes: 2
Reputation: 67
It's not an error. What it's saying is that by converting from an integer to an unsigned integer, the value will change if the integer is negative. There's really no "fix" for this; you just need to be careful what values the unsigned is taking from the signed. I'm guessing you're using unsigned because it needs to be 0 and above, so if anything, this will fix any accidentally-entered negative values.
Upvotes: -1