Почему выводит 1?
long int i = -0xffffffff;
std::cout << i;
0xffffffff имеет тип unsigned int †.
Результат применения унарного - к unsigned типам - это 2N - x (где N - размер типа в битах). Пруф.
Так что -0xffffffff = -(unsigned int)4294967295 = (unsigned int)(42949672956 - 4294967295) = (unsigned int)1.
Когда результат преобразуется в long, он, естественно, остается единицей.
† Это верно только если размер intа - 32 бита. Принцип такой:
Если целочисленный литерал не влезает в int, то компилятор будет пробовать типы большего размера, пока один из них не подойдет: int, unsigned int, long, unsigned long, и т. п.
(Такая последовательность типов используется, если литерал без суффикса, и не десятичный. Для десятичных без суффикса unsigned ... не проверяются. Почему? - ¯\_(ツ)_/¯, пруфы и подробности здесь.)
С 32-битными intами, первым подходит unsigned int.
С 64-битными - обычный int, и итоговый ответ будет -4294967295.
Оператор унарный минус, примененный к беззнаковому типу, дает результат аналогичный вычитанию этого числа из 2 в степени (количество бит в числе).
2^32 - 0xffffffff
4294967296 - 4294967295
1
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники