x86 documentation
От: rm822 Россия  
Дата: 16.08.10 14:15
Оценка: 8 (2)
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.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Сдвиг вправо на 32
От: OdesitVadim Украина  
Дата: 16.08.10 13:43
Оценка: 4 (1)
Здравствуйте, 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 сразу, если оптимизирует, или не делать этого...
Re[3]: Сдвиг вправо на 32
От: Кодт Россия  
Дата: 16.08.10 13:59
Оценка: 4 (1)
Здравствуйте, 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) ;
Перекуём баги на фичи!
Re[3]: Сдвиг вправо на 32
От: ilnar Россия  
Дата: 16.08.10 14:33
Оценка: 2 (1)
Здравствуйте, 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
Сдвиг вправо на 32
От: alzt  
Дата: 16.08.10 13:32
Оценка:
Добрый день.

Не совсем С++, но думаю здесь ответят.
    unsigned int a = 0xF0000000;
    unsigned int b = a>>31; //b ==1 как и ожидается

    unsigned int c = a>>32;//c-?


Непонятно почему в приведённом примере c не равняется 0. Почему такое ограничение?
Ладно бы сдвиг был на 33 бита, но в сдвиге на 32 все должно быть в порядке.
Re: Сдвиг вправо на 32
От: Abyx Россия  
Дата: 16.08.10 13:34
Оценка:
Здравствуйте, alzt, Вы писали:

если компилятор — MSVC, читайте MSDN, там все написано
по стандарту это UB
In Zen We Trust
Re: Сдвиг вправо на 32
От: Pavel Dvorkin Россия  
Дата: 16.08.10 13:36
Оценка:
Здравствуйте, 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.

VS 2008
With best regards
Pavel Dvorkin
Re[2]: Сдвиг вправо на 32
От: alzt  
Дата: 16.08.10 13:39
Оценка:
Здравствуйте, 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 слишком большим числом.

Подобное воспроизводится не только на С++.
Re[4]: Сдвиг вправо на 32
От: alzt  
Дата: 16.08.10 18:06
Оценка:
Здравствуйте, 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;


А вообще наткнулся я на это следующим образом. Была функция с некоторой хитрой битовой арифметикой:

//упрощённый вариант
unsigned getVal(int bits) {
    assert(bits>0 && bits<32);
    ...
    unsigned x = buffer >> (32 - bits);

    return x;
}

В некоторый момент понял, что проще всего расширить контракт функции таким образом, чтобы она могла принимать 0 в качестве входного параметра. В результате при интуитивном вычислении на выходе должен был получиться тоже 0, что меня вполне устраивало, но суровая реальность заставила искать другие пути решения.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.