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

Почему 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, мне просто интересно, почему.

4b9b3361

Ответ 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 не рекомендуются, потому что если они идут отрицательно, то они переполняются и уходят на самое большое число.