Intereting Posts
Как проверить файлы заголовков и библиотечные функции в CMake, как это делается в Autotools? SDL2.0 Альтернатива для SDL_Overlay Левая панель printf с пробелами Как работать с субматрицей в матрице по указателю? передача массива структуры в качестве параметра функции состояние гонки pthread, подозрительное поведение Документация файлов Vala vapi Как проверить, находится ли точка (x, y) внутри многоугольника в декартовой системе координат? Как работает оператор switch? не может генерировать файл ядра после изменения пользователя от root до никого на языке c Как скомпилировать программу Linux C для запуска на другой машине Linux? Компилятор не останавливается на scanf () для ввода Как устранить предупреждение для передачи многомерного массива как многомерного массива const? Segfault на IA-64, но не на IA-32 Когда / почему это плохая идея использовать функцию fscanf ()?

каково значение ~ 0 в C?

Я хочу получить значение INT_MIN и INT_MAX , и я пробовал ~0 и ~0 >> 1 так как самый левый бит является битом знака. Я получил их обоих -1 .

Это настолько запутанно, что почему ~0 оказывается 0xffffffff и ~0 >> 1 равным 0x7fffffff ?

Использование:

 ~0U >> 1 

Суффикс ‘U’ для неподписанного поведения сдвига.

поэтому, смущенно, почему же ~0 оказывается равным 0xffffffff ?

Смотрите, что такое 0 в четырех байтах:

 BIT NUMBER 31 0 ▼ ▼ number bits 0000 0000 0000 0000 0000 0000 0000 0000 ▲ ▲ MSB LSB LSB - Least Significant Bit (numbered 0) MSB - Most Significant Bit (numbered 31) 

Теперь ~ побитовым не является оператором, а затем переворачивает все биты в 0 как:

 BIT NUMBER 31 0 ▼ ▼ number bits 1111 1111 1111 1111 1111 1111 1111 1111 ▲ ▲ MSB LSB 

Из-за MSB = 1 это представление рассматривается как отрицательное число, и его величина находит, используя математику 2’complement, которая равна -1 .

Как?

Что такое 1 ? это:

 number bits 0000 0000 0000 0000 0000 0000 0000 0001 ▲ ▲ MSB LSB 

1 дополнение 1

 number bits 1111 1111 1111 1111 1111 1111 1111 1110 ▲ ▲ MSB LSB 

2’complement? Добавьте 1 в дополнение, то есть:

 number bits 1111 1111 1111 1111 1111 1111 1111 1111 ▲ ▲ MSB LSB 

это же, когда вы получаете ~0 ? поэтому вы получаете -1 выход.

Теперь >> оператор сдвига?

В большинстве случаев реализация оператора C >> определяется как арифметический сдвиг вправо, который сохраняет знаковый бит MSB. Итак, ~0 >> 1 отмечает, но -1 остается таким же.

6.5.7 [Операторы побитового сдвига]

5 Результат E1 >> E2 – это E1 правым смещением позиций E2 . Если E1 имеет неподписанный тип, или если E1 имеет подписанный тип и неотрицательное значение, значение результата является неотъемлемой частью частного E1 / 2E2 . Если E1 имеет подписанный тип и отрицательное значение, результирующее значение определяется реализацией.

Требование – это то, что называется unsigned right shift >> и поведение, которое вам нужно, можно найти с использованием неподписанного числа, поэтому я суффикс U как 0U .

Как печатать INT_MIN и INT_MAX?

Поскольку печать INT_MIN и INT_MAX немного сложна (из-за неопределенного и поведения реализации установки MSB и переполнения бит) в C, поэтому я написал код следующим образом:

 #include  #include /* include for CHAR_BIT */ int main(){ int my_int_min = 1U << ((sizeof(int) * CHAR_BIT) - 1); int my_int_max = ~0U >> 1; printf("INT_MIN = %d\n", my_int_min); printf("INT_MAX = %d\n", my_int_max); return 0; } 

См. Его выполнение @ codepad , его вывод:

 INT_MIN = -2147483648 INT_MAX = 2147483647 

Как работает этот код?

Примечание для 32-битного диапазона номеров – [-2147483648, 2147483647] что равно [-2 31 , 2 31 -1 ] .

INT_MIN: -2 31 == -2147483648:

  1000 0000 0000 0000 0000 0000 0000 0000 ▲ ▲ MSB LSB 

В выражении 1U << ((sizeof(int) * CHAR_BIT) - 1) , я сдвигаю первый бит LSB (то есть 1), чтобы оставить большую часть в MSB, а поскольку в C установка знакового бита - неопределенное поведение, когда операнд , поэтому я использовал unsigned one 1U.

6.5.7 [Операторы побитового сдвига]

Результат E1 << E2 - это E1 левые сдвиговые позиции E2; освобожденные биты заполняются нулями. Если E1 имеет неподписанный тип, значение результата равно E1 × 2E2, уменьшенному на единицу больше, чем максимальное значение, представляемое в типе результата. Если E1 имеет подписанный тип и неотрицательное значение, а E1 × 2E2 представляется в типе результата, то это результирующее значение; в противном случае поведение не определено.

Еще один момент, который следует отметить, я использовал CHAR_BIT стандартный макрос, определенный в limits.h, который сообщает количество бит в одном символе в реализации C (помните: символ всегда имеет размер по одному байту, но количество бит в одном байте может быть различным на разных система не всегда гарантируется 8).

INT_MAX: 2 31 -1 == 2147483647

  0111 1111 1111 1111 1111 1111 1111 1111 ▲ ▲ MSB LSB 

0 имеет тип int . Итак, ~0 и ~0 >> 1 потому что продвижение типа типа

~ 0 – все 1s, и это -1 в дополнении 2, которое является стандартным представлением большинства современных реализаций.

Правильный сдвиг в C определяется реализацией. Но большинство реализаций определяют >> как арифметический сдвиг, когда тип подписывается, и логический сдвиг, когда тип без знака

Так как ~0 является int , который является подписанным типом, ~0 >> 1 будет арифметическим сдвигом вправо. Следовательно, значение увеличивается до знака, поэтому значение должно быть равным 1 с

Вам нужно сделать unsigned(~0) >> 1

Невозможно получить INT_MIN и INT_MAX, потому что в C существует 3 разных типа подписанных типов

~0 равно -1 . Каждая реализация C, с которой вы, вероятно, 0xffffffff использует два дополнения для целых чисел со 0xffffffff , поэтому 0xffffffff равно -1 (предполагая 32-разрядные целые числа). ~0 >> 1 является эквивалентом деления -1 на 2 ; поскольку мы выполняем целочисленную арифметику, результат равен -1 .

Значение всего бита set int зависит от представления знака, которое ваша платформа имеет для int . Вот почему были изобретены macros INT_MIN и INT_MAX , и нет способа вычислить эти значения переносимым образом.

Основываясь на статье wikipedia , C обычно реализует арифметический сдвиг. Это означает, что когда вы 0xffffffff величину 0xffffffff , левый бит (бит знака) 1 будет сохранен, как вы заметили.

Однако Wikipedia также упоминает следующее, поэтому вы получите логический сдвиг (результат 0x7fffffff ), если вы используете неподписанный тип.

Оператор >> в C и C ++ не обязательно является арифметическим сдвигом. Обычно это только арифметический сдвиг, если он используется со знаком целочисленного типа с левой стороны. Если вместо этого используется целочисленный тип без знака, это будет логический сдвиг.

числа хранятся в комплименте 2, поэтому ~00XFFFFFFFF который равен -1.
поэтому FFFFFFF(1111) >>1 дает (1111)FFFFFFF = 0XFFFFFFFF = -1 .

При смещении значения unsigned оператор >> в C является logical shift . При смещении signed значения оператор >> является arithmetic shift .
Итак, ~0U >> 1 дает (1111)FFFFFFF = 0XFFFFFFFF .

В 32-битной системе 00x00000000 . ~ является побитовым оператором , который превращает каждый 0 бит в 1 и наоборот. Поэтому ~0 ( ~0x00000000 ) дает 0xffffffff .

Это, в свою очередь, интерпретируется как -1 в дополнении 2 .