shl, shr — Shift Left, Shift Right
These instructions shift the bits in their first operand's contents left and right, padding the resulting empty bit positions with zeros. The shifted operand can be shifted up to 31 places. The number of bits to shift is specified by the second operand, which can be either an 8-bit constant or the register CL. In either case, shifts counts of greater then 31 are performed modulo 32.
Здравствуйте, alzt, Вы писали:
A>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>warning C4293: '>>' : shift count negative or too big, undefined behavior PD>>If a shift count is negative or too large, the behavior of the resulting image is undefined.
PD>>VS 2008
A>Но почему так сделано? A>Ну никак не поворачивается язык назвать 32 слишком большим числом.
A>Подобное воспроизводится не только на С++.
Вообще то это в процессоре ограничение. там для здвига используются только последние 5 бит.
А вот компилятор, если видит сдвиг на 33, то может подсунуть 0 сразу, если оптимизирует, или не делать этого...
Здравствуйте, alzt, Вы писали:
A>Но почему так сделано? A>Ну никак не поворачивается язык назвать 32 слишком большим числом.
Потому что это напрямую кодируется соответствующей инструкцией процессора.
Известно, что многие процессоры предсказуемо выполняют сдвиг, только если сдвигатель находится в допустимых пределах (разрядность регистра).
Вне этих пределов действие вырождается до обнуления, — и разработчики процессоров небезосновательно считают, что если кому такое нужно, пусть он явно обнулит вместо сдвига.
А разработчики компиляторов считают, что процессоры — это уже данность, а вставлять дополнительные проверки — это загромождать объектный код, по большей части, бесполезными действиями.
Так что, если в каком-то единичном месте возникла нужда сдвигать на произвольное значение, — вот в этом месте и надо написать безопасный код вида
int a, s;
int const BITS = sizeof(int)*CHAR_BITS;
int b =
(s >= BITS-1) ? (a>>(BITS-1)) : // арифметический сдвиг вправо (с расширением знака)
(s >= 0) ? (a>>s) : //
(s <= 1-BITS) ? (0) : // сдвиг влево, обнуляющий все значащие биты
(a<<-s) ;
Здравствуйте, alzt, Вы писали:
A>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>warning C4293: '>>' : shift count negative or too big, undefined behavior PD>>If a shift count is negative or too large, the behavior of the resulting image is undefined.
PD>>VS 2008
A>Но почему так сделано? A>Ну никак не поворачивается язык назвать 32 слишком большим числом.
A>Подобное воспроизводится не только на С++.
так процессор работает, по крайней мере у интела, сдвиг производится на число получаемое из 5 младших бит.
если левый операнд 64-х битный, то 6 бит
long long a = 0xF0000000LL;
unsigned int b = a>>31; //b ==1 как и ожидается
unsigned int c = a>>32;// 0
unsigned int a = 0xF0000000;
unsigned int b = a>>31; //b ==1 как и ожидаетсяunsigned int c = a>>32;//c-?
Непонятно почему в приведённом примере c не равняется 0. Почему такое ограничение?
Ладно бы сдвиг был на 33 бита, но в сдвиге на 32 все должно быть в порядке.
Здравствуйте, alzt, Вы писали:
A>Добрый день.
A>Не совсем С++, но думаю здесь ответят. A>
A> unsigned int a = 0xF0000000;
A> unsigned int b = a>>31; //b ==1 как и ожидается
A> unsigned int c = a>>32;//c-?
A>
warning C4293: '>>' : shift count negative or too big, undefined behavior
If a shift count is negative or too large, the behavior of the resulting image is undefined.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>warning C4293: '>>' : shift count negative or too big, undefined behavior PD>If a shift count is negative or too large, the behavior of the resulting image is undefined.
PD>VS 2008
Но почему так сделано?
Ну никак не поворачивается язык назвать 32 слишком большим числом.
Здравствуйте, ilnar, Вы писали:
I>так процессор работает, по крайней мере у интела, сдвиг производится на число получаемое из 5 младших бит. I>если левый операнд 64-х битный, то 6 бит
I>long long a = 0xF0000000LL; I>unsigned int b = a>>31; //b ==1 как и ожидается I>unsigned int c = a>>32;// 0
Точно. Я проверял на 32-х разрядном. Там c было равно b. Т.к. по видимому этот код был эквивалентен следующему:
unsigned int c = a>>0;
А вообще наткнулся я на это следующим образом. Была функция с некоторой хитрой битовой арифметикой:
В некоторый момент понял, что проще всего расширить контракт функции таким образом, чтобы она могла принимать 0 в качестве входного параметра. В результате при интуитивном вычислении на выходе должен был получиться тоже 0, что меня вполне устраивало, но суровая реальность заставила искать другие пути решения.