Почему unsigned int x = -1 и int y = ~ 0 имеют одинаковое двоичное представление? - PullRequest
12 голосов
/ 29 июня 2010

В следующем сегменте кода, что будет:

  • результат функции
  • значение х
  • значение у
    {
         unsigned int x=-1;
         int y;
         y = ~0;
         if(x == y)
             printf("same");
         else
             printf("not same");
     }
a. same, MAXINT, -1
b. not same, MAXINT, -MAXINT
c. same , MAXUINT, -1
d. same, MAXUINT, MAXUINT
e. not same, MAXINT, MAXUINT

Может кто-нибудь объяснить мне, как это работает, или может просто объяснить фрагмент ??

Я знаю, что это два дополнения и т. Д .. Каково значение MAXINT и -1? Это из-за неподписанных int и int вещь - я прав?

Ответы [ 5 ]

12 голосов
/ 29 июня 2010

unsigned int x=-1;

1 является целочисленным литералом и имеет тип int (потому что он соответствует int). Унарный -, примененный к int, не вызывает дальнейшего повышения, поэтому -1 - это int со значением -1.

При преобразовании в unsigned int используется арифметика по модулю 2 ^ N, где N - количество битов значения в unsigned int. x имеет значение 2 ^ N - 1, равное UINT_MAX (Что такое MAX_UNIT?).

int y;
y = ~0;

Снова 0 - это тип int, в C все разрешенные представления int должны иметь все биты значения int, представляющего 0 как 0. Опять не происходит повышение для унарного ~, так что ~0 - это int со всеми битами значения, равными 1. То, что это значение, зависит от реализации, но оно отрицательно (бит знака будет установлен), поэтому определенно не имеет значения UINT_MAX или INT_MAX. Это значение сохраняется в y без изменений.

if(x == y)
    printf("same");
else
    printf("not same");

В этом сравнении y будет преобразовано в unsigned int для сравнения с x, который уже равен unsigned int. Поскольку y имеет значение реализации, значение после преобразования в unsigned int все еще определяется реализацией (хотя само преобразование по модулю 2 ^ N и полностью определено). Результат сравнения по-прежнему определяется реализацией.

Итак, в заключение:

реализация определена, UINT_MAX, реализация определена

На практике на своем дополнении:

не то же самое, UINT_MAX, -0 (он же 0)

знак плюс величина:

не то же самое, UINT_MAX, INT_MIN

два дополнения:

то же, UINT_MAX, -1

8 голосов
/ 29 июня 2010

Если вы запустите эту программу, вы увидите, что ответ a неправильный , а c правильный ответ:

#include <stdio.h>
#include <limits.h>

int main() {
    unsigned int x=-1;
    int y;
    y = ~0;
    if(x == y)
        printf("same\n");
        if(x==INT_MAX) printf("INT_MAX\n");
        if(x==UINT_MAX) printf("UINT_MAX\n");
    else
        printf("not same");
    return 0;
}
8 голосов
/ 29 июня 2010

Это довольно легко.Дополняющее представление двойки -1 равно 0xFFFFFFFF.Следовательно, это то, что содержит x.

Оператор дополнения (~) переворачивает все биты.Таким образом, дополнение 0 - это 32-разрядное число со всеми битами, установленными в 1 или 0xFFFFFFFF.

Редактировать: Как указано в комментарияхОтвет не A. Если бы это было так, то было бы сказано, что 0x7FFFFFFF и 0xFFFFFFFF одинаковы.Они не.Реальный ответ - C (при условии, что MAXUNIT - опечатка;)).

2 голосов
/ 29 июня 2010

Это из-за дополнения до двух

Переворот битов приводит к битовому шаблону, который соответствует -1

1 голос
/ 29 июня 2010

Так как в первом unsigned int вы ставите -1, но с точки зрения unsigned int это 0xFFFFFFFF (именно так целые отрицательные числа хранятся в компьютере); во втором случае побитовое не совсем не смотрит на «вид» и «преобразует» 0 в 1 и наоборот, поэтому все нули 0 становятся 1 (глядя на биты), поэтому вы получаете 0xFFFFFFFF.

Следующий вопрос: почему сравнение целого без знака с целым числом со знаком не различает их? (численно 4294967295, конечно, не равен -1, хотя их представление в компьютере одинаково). В самом деле, это возможно, но ясно, что C не требует такого различия, и это «естественно», поскольку обработчик не может сделать это самостоятельно (я не уверен, что это последнее предложение всегда правда, ... но это для большинства процессоров): чтобы учесть это различие в asm, вы должны добавить дополнительный код.

С точки зрения C, вы должны решить, следует ли приводить int к unsigned int или со знаком int в unsigned int. Но отрицательное число не может быть преобразовано в беззнаковое, конечно, и, с другой стороны, беззнаковое число может вызвать переполнение (например, для 4294967295 вам нужен 64-битный регистр (или 33-битный регистр!), Чтобы иметь возможность иметь он все равно сможет рассчитать его отрицательное значение) ...

Вероятно, наиболее естественным является избегать странного приведения и разрешать сравнение с процессором, которое в этом случае приводит к 0xFFFFFFFF (-1 на 32-битной) по сравнению с 0xFFFFFFFF (~ 0 на 32-битной), которые то же самое, и больше в общем, одно можно рассматривать как MAXUINT (максимальное целое число без знака, которое может быть сохранено), а другое как -1. (Взгляните на свою машину limits.h включите, чтобы проверить)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...