Что происходит здесь, это целочисленное переполнение, которое равно undefined behavior, потому что точное представление целых чисел со знаком не определено.
На практике, однако, большинство машин используют представление дополнения 2 для целых чисел со знаком, и эта конкретная программа использует это.
0x80000000
- целочисленная константа без знака. -
отрицает это, меняя выражение на подписанное. Предполагая, что int
32-бит в вашей системе, это значение все еще подходит. Фактически, это наименьшее значение, которое может содержать подписанный 32-разрядный int
, а шестнадцатеричное представление этого числа - 0x80000000
.
При добавлении номеров в представлении дополнений 2, у него есть функция, которая вам не нужно беспокоиться о знаке. Они добавляются точно так же, как и беззнаковые числа.
Так что, когда мы добавляем x
и y
, мы получаем следующее:
0x80000000
+ 0x80000000
-------------
0x100000000
Поскольку int
в системе является 32-разрядным, лишь нижним 32 бит сохраняется. И значение этих бит равно 0.
Снова обратите внимание, что это фактически неопределенное поведение. Он работает, потому что ваша машина использует представление дополнения 2 для целых чисел со знаком, а int
- 32-разрядная. Это характерно для большинства машин/компиляторов, но не для всех.
Да, это переполнение. Нет, C обычно не предупреждает или не исключает исключения при переполнении целых чисел. Вы видите 0, потому что нижние 32 бита фактического ответа равны 0, и когда происходит переполнение целого числа, вы, как правило, получаете ответ по модулю 4294967296, то есть по модулю 2^32. –