Почему unsigned int x = -1 и int y = ~ 0 имеют одинаковое двоичное представление?
В следующем сегменте кода будет:
- результат функции
- значение x
- значение y
{
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
Может кто-нибудь объяснить мне, как это работает или может просто объяснить фрагмент?
Я знаю это о двух дополнениях n и т.д.
Каково значение MAXINT и -1?
Это из-за неподписанных int и int вещей - я прав?
Ответы
Ответ 1
Если вы запустите эту программу, вы увидите, что ответ 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;
}
Ответ 2
unsigned int x=-1;
1
является целым литералом и имеет тип int
(поскольку он соответствует int
). Unary -
, примененный к int
, не вызывает дальнейшего продвижения, поэтому -1
является int
со значением -1
.
При преобразовании в арифметику unsigned int
modulo 2 ^ N, где N - число бит значения в unsigned int
. x
имеет значение 2 ^ N - 1, которое UINT_MAX
(What 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 (aka 0)
знак плюс величина:
не то же самое, UINT_MAX
, INT_MIN
два дополнения:
то же самое, UINT_MAX
, -1
Ответ 3
Его довольно легко. Представление двойного дополнения -1 равно 0xFFFFFFFF. Следовательно, это то, что содержит x.
Оператор дополнения (~) переворачивает все биты. Таким образом, дополнение 0 представляет собой 32-битное число со всеми битами, установленными в 1 или 0xFFFFFFFF.
Изменить: как указано, он комментирует. Ответ не A. Если бы это было тогда, было бы сказано, что 0x7FFFFFFF и 0xFFFFFFFF одинаковы. Они не. Реальный ответ: C (Предполагая, что MAXUNIT - это опечатка;)).
Ответ 4
Это из-за twos-complement
Перевертывание битов приводит к битовой схеме, которая соответствует -1
Ответ 5
Так как в первом беззнаковом int вы помещаете -1, но из неподписанной int точки зрения это 0xFFFFFFFF (это то, как отрицательные целые числа хранятся в компьютере); во втором случае побитовое не вообще не смотрит на "вид" и "преобразует" 0 в 1 и наоборот, поэтому все нули 0 становятся 1 (смотря на биты), поэтому вы получаете 0xFFFFFFFF.
Следующий вопрос: почему сравнение целого числа без знака со знаком целого не отличает их? (численно 4294967295, конечно, не равно -1, хотя их представление в компьютере такое же). В самом деле, это возможно, но ясно, что C не предусматривает такого различия, и это "естественно", поскольку процессор не может сделать это самостоятельно (я не уверен, что это последнее предложение всегда true,... но это для большинства процессоров): чтобы принять во внимание это различие в asm, вам нужно добавить дополнительный код.
С точки зрения C вам нужно решить, следует ли вводить int в unsigned int или подписали int в unsigned int. Но отрицательное число не может быть записано в непознанный, и, с другой стороны, беззнаковое число может вызвать переполнение (например, для 4294967295 вам нужен 64-битный регистр (или 33-битный реестр!), Чтобы иметь возможность иметь он и еще сможет вычислить его отрицательное значение)...
Так что, скорее всего, самое естественное - избегать странного литья и разрешить сравнение "cpu like", которое в этом случае приводит к 0xFFFFFFFF (-1 на 32 бит) по сравнению с 0xFFFFFFFF (~ 0 на 32 бит), которые то же самое и больше в генетическом можно рассматривать как MAXUINT (максимальное целое без знака, которое может быть удержано), а другое как -1. (Посмотрите на свой аппарат limits.h
включить, чтобы проверить его)