В вашей программе не определено поведение, поэтому может произойти что угодно.
- Целочисленные литералы 0xF или 0xFF имеют тип
int
, что эквивалентно signed int
. На этой конкретной платформе int
, по-видимому, 32 бита.
- Целочисленный литерал 24 также является (подписанным)
int
.
- Когда компилятор оценивает операцию <<, оба операнда имеют (подпись) <code>int, поэтому неявные преобразования типов не выполняются. Поэтому результатом операции << также является (подпись) <code>int.
- Значение 0xF << 24 = 0x0F000000 помещается в (со знаком) <code>int как неотрицательное значение, поэтому все в порядке.
- Значение 0xFF << 24 = 0xFF000000 <em>не подходит in (подписано)
int
! Здесь вызывается неопределенное поведение, и может произойти все, что угодно.
ISO 9899: 2011 6.5.7 / 4:
"Результат E1 << E2 - это сдвинутые влево позиции E1 в битах E2; освобождены
биты заполнены нулями. "/ - / </p>
"Если E1 имеет тип со знаком и неотрицательное значение, а E1 × 2E2 представимо в типе результата,
тогда это итоговое значение; в противном случае поведение
не определено.
Так что выражение 0xFF << 24 нельзя использовать. Программа может свободно печатать любое значение мусора после этого. </p>
Но если мы проигнорируем это и сосредоточимся на 0x0F <24: </p>
- 0x0F000000 по-прежнему (подписано)
int
. Для этого применяется оператор ~.
- Результат - 0xF0FFFFFF, который все еще является целым числом со знаком. И почти в любой системе этот 32-битный гекс равен отрицательному числу в дополнении до двух.
- Это подписанное int преобразуется в тип uint64_t во время присваивания. Это выполняется в два этапа, сначала путем преобразования его в 64-разрядный со знаком, а затем путем преобразования 64-разрядного со знаком в 64-разрядный без знака.
Подобные ошибки приводят к тому, что стандарт кодирования MISRA-C содержит ряд правил, запрещающих небрежное использование целочисленных литералов в выражениях, подобных этому. Код, совместимый с MISRA-C, должен использовать суффикс u
после каждого целочисленного литерала (MISRA-C: 2004 10.6), а коду не разрешается выполнять побитовые операции со знаковыми целыми числами (MISRA-C: 2004 12.7).