Думаю, я схожу с ума от этого.
У меня есть фрагмент кода, который должен создать (беззнаковое) целое число с N
последовательными битами, установленными в 1. Точнее, у меня есть битовая маска, и в некоторых ситуациях я хотел бы установить это к твердому rnage.
У меня есть следующая функция:
void MaskAddRange(UINT& mask, UINT first, UINT count)
{
mask |= ((1 << count) - 1) << first;
}
Простыми словами: 1 << count
в двоичном представлении равно 100...000
(количество нулей равно count
), вычитание 1 из такого числа дает 011...111
, а затем мы просто сдвигаем его влево на first
.
Вышеизложенное должно дать правильный результат, когда соблюдается следующее очевидное ограничение:
first + count <= sizeof(UINT)*8 = 32
Обратите внимание, что следуеттакже корректно работают для "крайних" случаев.
count = 0
мы имеем (1 << count) = 1
, и, следовательно, ((1 << count) - 1) = 0
.count = 32
мы имеем (1 << count) = 0
, так как старший бит переполняется, и согласно правилам C/C++ операторы побитового сдвига не циклический. Тогда ((1 << count) - 1) = -1
(все биты установлены).Однако, как оказалось, для count = 32
формула не работает должным образом. Как выяснилось:
UINT n = 32;
UINT x = 1 << n;
// the value of x is 1
Кроме того, я использую MSVC2005 IDE. Когда я оцениваю приведенное выше выражение в отладчике, результат равен 0. Однако, когда я перешагиваю вышеприведенную строку, x
получает значение 1. Блокируя через дизассемблер, мы видим следующее:
mov eax,1
mov ecx,dword ptr [ebp-0Ch] // ecx = n
shl eax,cl // eax <<= LOBYTE(ecx)
mov dword ptr [ebp-18h],eax // n = ecx
Там нет действительно магия, компилятор только что использовал инструкцию shl
. Тогда кажется, что shl
не делает того, что я ожидал. Либо CPU решает проигнорировать эту инструкцию, либо сдвиг обрабатывается по модулю 32, либо не знаю что.
Мои вопросы:
shl
/ shr
?Заранее спасибо
Редактировать:
Спасибо за ответы.Я понял, что (1) shl
/shr
действительно обрабатывают операнд по модулю 32 (или & 0x1F) и (2) стандарт C/C++ рассматривает сдвиг более чем на 31 бит как неопределенный поведение.
Тогда у меня есть еще один вопрос. Как я могу переписать свое «маскирующее» выражение, чтобы охватить и этот крайний случай. Он должен быть без ветвления ( if
, ?
). Какое выражение было бы самым простым?