Подтвердить что ты не робот

Unsigned int (С++) vs uint (С#)

Ниже приведен код С#:

   static void Main(string[] args)
    {
        uint y = 12;
        int x = -2;
        if (x > y)
            Console.WriteLine("x is greater");
        else
            Console.WriteLine("y is greater");
    }

и это код С++:

int _tmain(int argc, _TCHAR* argv[])
{
unsigned int y = 12;
int x = -2;
if(x>y)
    printf("x is greater");
else
    printf("y is greater");

return 0;
}

Оба дают разные результаты. Я что-то пропустил? Любая идея?

4b9b3361

Ответ 1

С++ и С# - разные языки. У них есть разные правила для управления продвижением типов в случае сравнений.

В С++ и C их обычно сравнивают, как если бы они были беззнаковыми. Это называется "неподписанным сохранением". Компиляторы С++ и C традиционно используют "неподписанное сохранение", а использование этого указано в стандарте С++ и в K & R.

В С# они оба конвертируются в подписанные longs, а затем сравниваются. Это называется "сохранение ценности". С# указывает сохранение значения.

ANSI C также указывает сохранение значения, но только при работе с шортами и символами. Шорты и символы (подписанные и неподписанные) преобразуются с повышением в ints с сохранением значения, а затем сравниваются. Таким образом, если беззнаковый короткий был сопоставлен с подписанным коротким, результат получился бы как пример С#. Каждый раз, когда выполняется преобразование в больший размер, оно выполняется с сохранением значения, но если две переменные имеют одинаковый размер (а не короткие или символы), а каждый из них без знака, то они сравниваются как беззнаковые величины в ANSI C. Там хорошо обсуждается верхняя и нижняя стороны обоих подходов в часто задаваемом файле comp.lang.c.

Ответ 2

В С++, когда вы сравниваете unsigned int и a signed int, signed int преобразуется в unsigned int. Преобразование отрицательного signed int в unsigned int выполняется путем добавления UINT_MAX + 1, который больше, чем 12 и, следовательно, результата.

В С#, если вы получаете противоположный результат, это означает, что в С# оба выражения преобразуются в signed int signed long (long или System.Int64) 1 а затем сравнивается.

В С++ ваш компилятор должен предупредить вас:

предупреждение: сравнение выражений с подписью и без знака

Правило:
Всегда принимайте предупреждения, исходящие от компилятора!

1 Как справедливо указано в комментариях.

Ответ 3

Я не знаю о стандарте С#, но в стандарте С++ usual arithmetic conversions будет применяться к обоим оперантам реляционных операторов:

[......enum, floating point type involed......] 

— Otherwise, the integral promotions (4.5) shall be performed on both operands.
  Then the following rules shall be applied to the promoted operands:

    — If both operands have the same type, no further conversion is needed.

    — Otherwise, if both operands have signed integer types or both have
      unsigned integer types, the operand with the type of lesser integer
      conversion rank shall be converted to the type of the operand with
      greater rank.

    — 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.

    — Otherwise, if the type of the operand with signed integer type can
      represent all of the values of the type of the operand with unsigned
      integer type, the operand with unsigned integer type shall be converted
      to the type of the operand with signed integer type.

    — Otherwise, both operands shall be converted to the unsigned integer type 
      corresponding to the type of the operand with signed integer type.

Таким образом, когда unsigned int сравнивается с int, int будет преобразован в unsigned int, а -2 станет очень большим числом при преобразовании в unsigned int.