3

Unsigned int can not be negative by default. The compiler generates a warning. That's ok. But it is not clear for me why it does not generate a warning when I do the same thing in a function with a negative default value.

unsigned int test(unsigned int i = -1) { return i;} // no warnings! Why?

int main()
{
   unsigned int i = -1;        // warning warning C4245 (ok!)
   unsigned int j = test();    // no warnings!  Why?     
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
Tom Tom
  • 1,127
  • 11
  • 25

2 Answers2

3

I agree that your compiler ought to warn you of the default argument being negative. But compilers are not perfect. (And the standard permits the conversion of a negative integral value to an unsigned type.)

As for the warning on calling test(), how does the poor compiler know that test() will always return -1? The definition of the function might even be in a different compilation unit! (Granted it isn't in your case but compilers ought not to think that laterally when issuing warnings.)

If test were qualified with a constexpr then it would be a different matter and a compiler should be able to issue a warning.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    I tested with G++ 5.1, `constexpr` doesn't seem to generate any warnings in this case. – Frxstrem Apr 06 '16 at 11:03
  • Hum. Methinks it ought to. What about something like -1.1 which is actually UB? – Bathsheba Apr 06 '16 at 11:03
  • @Bathsheba You're saying that `unsigned int i = -1.1` is Undefined Behavior? – Jonathan Mee Apr 06 '16 at 11:12
  • It *certainly* is in C. Here's a question on exactly this from today: http://stackoverflow.com/questions/36443556/what-is-the-behaviour-on-converting-a-negative-floating-point-value-into-an-unsi/36443650#comment60501023_36443650 – Bathsheba Apr 06 '16 at 11:17
2

This conversion is allowed without a cast, as long as you are prepared to live with consequences:

Objects of unsigned integral types can be converted to corresponding signed types. However, such a conversion can cause misinterpretation of data if the value of the unsigned object is outside the range representable by the signed type.

When you do a conversion from signed to unsigned and back, the data will be preserved, though.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    It is indeed allowed (interestingly though -1.0 is allowed too but a floating point value lower than that is UB), but my reading of the (good) question is why the compiler doesn't *warn* you. – Bathsheba Apr 06 '16 at 11:00
  • When OP sets signed `-1` to `i`, the compiler knows that the data will be outside the range representable by `unsigned`, so it issues a warning. My only guess as to why C++ standard does not require a warning when a mis-interpretation *could* happen is that it guarantees identical bit representations, and the amount of potential harm from a no-op is limited. – Sergey Kalinichenko Apr 06 '16 at 11:07