Почему unsigned int 0xFFFFFFFF равно int -1?
В C или С++ сказано, что максимальное число, которое имеет тип size_t (неподписанный тип данных), может быть таким же, как литиевание -1 для этого типа данных. например, см. Недопустимое значение для size_t
Почему?
Я имею в виду, (говоря о 32-битных ints) AFAIK самый старший бит содержит знак в подписанном типе данных (то есть бит 0x80000000 для формирования отрицательного числа). то 1 - 0x00000001.. 0x7FFFFFFFF - наибольшее положительное число, которое может хранить тип данных int.
Тогда AFAIK двоичное представление -1 int должно быть 0x80000001 (возможно, я ошибаюсь). почему/как это двоичное значение преобразуется во что-то совершенно другое (0xFFFFFFFF) при литье ints в unsigned?? или.. как можно сформировать двоичный -1 из 0xFFFFFFFF?
Я не сомневаюсь, что в C: ((unsigned int) -1) == 0xFFFFFFFF или ((int) 0xFFFFFFFF) == -1 равно true, чем 1 + 1 == 2, мне просто интересно, почему.
Ответы
Ответ 1
C и С++ могут работать на разных архитектурах и машинных типах. Следовательно, они могут иметь разные представления чисел: два дополнения, а дополнение Одеса является наиболее распространенным. В общем, вы не должны полагаться на определенное представление в своей программе.
Для неподписанных целых типов (size_t
, являющихся одним из них), стандарт C (и, как мне кажется, стандартный С++) определяет точные правила переполнения. Короче говоря, если SIZE_MAX
- максимальное значение типа size_t
, то выражение
(size_t) (SIZE_MAX + 1)
гарантируется 0
, и поэтому вы можете быть уверены, что (size_t) -1
равно SIZE_MAX
. То же самое справедливо и для других неподписанных типов.
Обратите внимание, что это верно:
- для всех неподписанных типов,
- даже если базовая машина не представляет числа в Два дополнения. В этом случае компилятор должен убедиться, что идентификатор имеет значение true.
Кроме того, это означает, что вы не можете полагаться на конкретные представления для подписанных типов.
Изменить: чтобы ответить на некоторые из комментариев:
Скажем, у нас есть фрагмент кода, например:
int i = -1;
long j = i;
В присвоении j
есть преобразование типа. Предполагая, что int
и long
имеют разные размеры (большинство [всех?] 64-битных систем), битовые шаблоны в ячейках памяти для i
и j
будут отличаться, поскольку они имеют разные размеры, Компилятор гарантирует, что значения i
и j
равны -1
.
Аналогично, когда мы делаем:
size_t s = (size_t) -1
Происходит преобразование типа. -1
имеет тип int
. Он имеет бит-шаблон, но это не имеет значения для этого примера, потому что, когда преобразование в size_t
происходит из-за броска, компилятор будет переводить значение в соответствии с правилами для типа (size_t
в этом случае), Таким образом, даже если int
и size_t
имеют разные размеры, стандарт гарантирует, что значение, сохраненное в s
выше, будет максимальным значением, которое может принимать size_t
.
Если мы это сделаем:
long j = LONG_MAX;
int i = j;
Если LONG_MAX
больше, чем INT_MAX
, то значение в i
определяется реализацией (C89, раздел 3.2.1.2).
Ответ 2
Он назвал два дополнения. Чтобы сделать отрицательное число, инвертируйте все биты, затем добавьте 1. Итак, чтобы преобразовать 1 в -1, инвертируйте его в 0xFFFFFFFE, затем добавьте 1, чтобы сделать 0xFFFFFFFF.
Что касается этого, Wikipedia говорит:
Система с двумя дополнениями имеет то преимущество, что не требует, чтобы схема сложения и вычитания проверяла признаки операндов, чтобы определить, следует ли добавлять или вычитать. Это свойство упрощает реализацию системы и позволяет легко обрабатывать арифметику с более высокой точностью.
Ответ 3
Ваш первый вопрос, почему (unsigned)-1
дает максимально возможное значение без знака, случайно ассоциируется только с двумя дополнениями. Причина -1, приводимая к неподписанному типу, дает наибольшее значение, возможное для этого типа, потому что стандарт говорит, что неподписанные типы "следуют законам арифметики по модулю 2 n где n - количество бит в представление значения этого определенного размера целого числа."
Теперь, для 2-х дополнений, представление максимально возможного значения без знака и -1 окажется одинаковым - но даже если аппаратное обеспечение использует другое представление (например, 1 дополнение или знак/величина), преобразование -1 в unsigned type должен по-прежнему выдавать максимально возможное значение для этого типа.
Ответ 4
Два дополнения очень приятны для выполнения вычитания точно так же, как добавление:)
11111110 (254 or -2)
+00000001 ( 1)
---------
11111111 (255 or -1)
11111111 (255 or -1)
+00000001 ( 1)
---------
100000000 ( 0 + 256)
Ответ 5
Это двухкомпонентное кодирование.
Основной бонус заключается в том, что вы получаете ту же самую кодировку, используете ли вы беззнаковый или подписанный int. Если вы вычтите 1 из 0, целое просто обернется. Поэтому 1 меньше 0 - 0xFFFFFFFF.
Ответ 6
Поскольку бит-шаблон для int
-1 - FFFFFFFF в шестнадцатеричном формате без знака.
11111111111111111111111111111111 двоичный неподписанный.
Но в int первый бит означает, является ли он отрицательным.
Но в unsigned int первый бит - это просто дополнительный номер, потому что unsigned int не может быть отрицательным. Таким образом, дополнительный бит делает unsigned int способным хранить большие числа.
Как и для unsigned int 11111111111111111111111111111111 (двоичный) или FFFFFFFF (шестнадцатеричный) - это самое большое число, которое может хранить uint.
Unsigned Ints не рекомендуются, потому что если они идут отрицательно, то они переполняются и уходят на самое большое число.