11

We had a bug in our code coming from the line

unsigned int i = -1;

When the code was originally written, is was i = 0 and thus correct. Using -Wall -Wextra, I was a bit surprised that gcc didn't warn me here because -1 does not fit in an unsigned int.

Only when turning on -Wsign-conversion this line becomes a warning - but with it many many false positives. I am using a third party library which does array-like operations with signed int's (although they cannot be < 0), so whenever I mix that with e.g. vector, I get warnings - and I don't see the point in adding millions of casts (and even the 3rd party headers produce a lot of warnings). So it is too many warnings for me. All these warnings are that the conversion "may change the sign". That's fine because I know it doesn't in almost all of the cases.

But with the assignment mentioned above, I get the same "may change" warning. Shouldn't this be "Will definitely change sign!" instead of "may change"? Is there any way to emit warnings only for these "will change" cases, not for the maybe cases?

Raubtier
  • 293
  • 4
  • 8
  • 1
    Even the definite sign change is often used deliberately. For example, `std::string` has `static const size_type npos = -1;`. – interjay Nov 23 '15 at 13:26
  • 1
    [-1 is used with unsigned types](http://stackoverflow.com/q/22801069/1708801) since it's result is well defined by the standard. – Shafik Yaghmour Nov 23 '15 at 13:27
  • using unsigned to make sure variable won't be negative is another mistake :D – Angelus Mortis Nov 23 '15 at 13:29
  • 2
    @AngelusMortis Nah. It’s important to be precise here: using `unsigned` to ensure that a number won’t be negative works and is absolutely the right thing to do. What it *doesn’t* do (but see answer below) is prevent *assignment* and conversion of a negative number. But these are distinct concerns. – Konrad Rudolph Nov 23 '15 at 13:31
  • 2
    @KonradRudolph meh I've just started learning c++, was just trying to make an impression , I'm more of a idiot :D – Angelus Mortis Nov 23 '15 at 13:33
  • I believe you have run into another concession to the C programming language. I have run into mixing of signed and unsigned values and variables in older C code quite a bit. – Richard Chambers Nov 23 '15 at 13:36

2 Answers2

5

Initialize it with curly braces :

unsigned int i{-1};

GCC outputs :

main.cpp:3:22: error: narrowing conversion of '-1'
from 'int' to 'unsigned int' inside { } [-Wnarrowing]
     unsigned int i{-1};

Note that it does not always cause an error, it might be a warning or disabled altogether. You should try it with your actual toolchain.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Quentin
  • 62,093
  • 7
  • 131
  • 191
1

But with the assignment mentioned above, I get the same "may change" warning. Shouldn't this be "Will definitely change sign!" instead of "may change"?

That's odd. I tested a few versions of gcc in the range of (4.6 - 5.2) and they did give a different warning for unsigned int i = -1;

warning: negative integer implicitly converted to unsigned type [-Wsign-conversion]

That said, they are indeed controlled by the same option as the may change sign warnings, so...

Is there any way to emit warnings only for these "will change" cases, not for the maybe cases?

As far as I know, that's not possible. I'm sure it would be possible to implement in the compiler, so if you want a separate option to enable the warning for assigning a negative number - known at compile time - to an unsigned variable, then you can submit a feature request. However, because assigning -1 to an unsigned variable is such a common and usually perfectly valid thing to do, I doubt such feature would be considered very important.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Ok, thanks for the answer. Indeed, the warning text IS different. I was just looking at the wrong line between all the other "may" warnings. Then it seems my preferred solution is to use more and more `auto` variables. – Raubtier Nov 23 '15 at 15:03