6

Can somebody tell me why the if condition is false?

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    int a;
    unsigned int ua;

    a = -1;
    ua = a;

    cout << "ua: " << ua << endl;
    if (ua != -1)
        cout << "Is unsigned" << endl;
    else
        cout << "Is signed" << endl;

    return 0;
}

I mean, here ua == int_max_value, it's NOT -1, but when I run this, the output is

Is signed

T.C.
  • 133,968
  • 17
  • 288
  • 421
harryPoker
  • 85
  • 6
  • 2
    `-1` is converted to `unsigned int` for that comparison. – T.C. Aug 27 '14 at 02:33
  • if -1 is converted to unsigned int, How can it hold -1? I mean, -1 IS signed :S – harryPoker Aug 27 '14 at 02:37
  • 2
    `-1` is converted using two's complement arithmetic, resulting in `UINT_MAX`. It's just that C++ has a very strong "tendency" to convert everything into unsigned integers (the exact rules for when this happens are rather complex; see the C++ standard for details). – Rufflewind Aug 27 '14 at 02:39
  • @harryPoker: It doesn't. But it becomes signed again for the conversion! – Lightness Races in Orbit Aug 27 '14 at 02:54

2 Answers2

4

!= and == on arithmetic types perform what is known as the usual arithmetic conversions on their operands. As relevant here, given one operand of type unsigned X and one operand of type signed X, where X is one of int, long and long long, the usual arithmetic conversions convert the signed operand to the unsigned type before the comparison takes place.

Hence, when you compare ua (of type unsigned int) and -1 (of type signed int), -1 is converted to type unsigned int (conceptually, by adding 232 to it, assuming 32-bit int), and the result compares equal to the value of ua.

T.C.
  • 133,968
  • 17
  • 288
  • 421
1

This is expected behavior, != will perform the usual arithmetic conversions on it's operands if they are arithmetic types. This is covered in the draft C++ standard section 5.10 Equality operators which says:

If both operands are of arithmetic or enumeration type, the usual arithmetic conversions are performed on both operands; each of the operators shall yield true if the specified relationship is true and false if it is false.

in this case this will lead to the integer promotion which will see -1 converted to unsigned int. This is covered in section 5 paragraph 10 which ends up saying:

Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Note that the particular paragraph quoted changed in C++14, but the behavior remains the same. The relevant paper is [N3624](http://open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3624.html). – T.C. Aug 27 '14 at 02:43
  • Also, the conversion of `-1` to unsigned is not integral promotion. – T.C. Aug 27 '14 at 02:48
  • @T.C. C++14 is a simpler quote ... wrt to the integral promotions section `5 p 10` says `Otherwise, the integral promotions (4.5) shall be performed on both operands` – Shafik Yaghmour Aug 27 '14 at 02:50
  • @ShafikYaghmour And if you look at the section cited, integral promotions don't apply to operands whose type is already `int`. The conversion to `unsigned` happens after the integral promotions (if any) are applied. – T.C. Aug 27 '14 at 02:54
  • @T.C. in C99 and C11 it actually says `All other types are unchanged by the integer promotions.` So I have always thought of it as a promotion even though no change is required but perhaps my interpretation is incorrect. – Shafik Yaghmour Aug 27 '14 at 02:59