Sirish Kumar Bethala
Sirish Kumar Bethala

Reputation: 9259

Compiler warnings conversion

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

Answers (3)

Shafik Yaghmour
Shafik Yaghmour

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

Jarod42
Jarod42

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

Kelvin Shadewing
Kelvin Shadewing

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

Related Questions