Почему этот побитовый сдвиг-правый кажется неработоспособным?

Может кто-нибудь объяснить мне, почему маска вообще не смещена вправо? Вы можете использовать что-либо вместо этого 1, и результат будет таким же.

unsigned mask = ~0 >> 1;
printf("%u\n", mask);

Ответ 1

Это проблема типа. Если вы отбрасываете 0 в unsigned, это будет хорошо:

unsigned mask = ~ (unsigned) 0 >> 1;
printf("%u\n", mask);

Редактировать в комментариях: или использовать нотацию беззнакового литерала, что намного более красноречиво.:)

unsigned mask = ~0u >> 1;
printf("%u\n", mask);

Ответ 2

Расширение знака

Что происходит ~0 - это int со всеми установленными битами (-1). Теперь вы сдвигаетесь вправо на 1; так как он -1, расширение знака сохраняет самый старший бит, поэтому он остался подписанным (это не то, что вы ожидали). Затем он преобразуется в unsigned, как вы ожидаете.

Ответ 3

Попробуйте следующее:

unsigned mask = (unsigned) ~0 >> 1;
printf("%08x\n", mask);

RHS присваивания рассматривается как подписанное количество, если вы не произнесете его, а это означает, что вы видите расширение знака без трансляции. (Я также изменил ваш оператор печати, чтобы отобразить число в шестнадцатеричном формате, которое мне легче декодировать.)

Ответ 4

~ 0 - строка из них. Оператор → сдвигает их, и в значении знака он сдвигает их в биты более высокого порядка. Таким образом, вы можете переместить все, что хотите, результат не изменится.