Выполнить логический сдвиг, используя оператор арифметического сдвига в C

Сейчас я читаю книгу Computer Systems: Programmer Perspective.

Одна проблема в книге говорит о том, чтобы выполнить логический сдвиг вправо над целым числом со знаком, я не могу понять, как начать с этого.

Вот собственно вопрос из книги:

Введите код для следующих функций C.

  • Функция srl выполняет логический сдвиг вправо, используя арифметический сдвиг вправо (заданный значением xsra), за которым следуют другие операции, не включая сдвиги вправо или деление.

  • Функция sra выполняет арифметический сдвиг вправо, используя логический сдвиг вправо (заданный значением xsrl), за которым следуют другие операции, не включая сдвиги вправо или деление.

Вы можете использовать вычисление 8*sizeof(int) для определения w, количества битов в типе данных int. Величина переключения k может варьироваться от 0 до w − 1.

unsigned srl(unsigned x, int k) {
    /* Perform shift arithmetically */
    unsigned xsra = (int) x >> k;
    .
    .
    .
}

int sra(int x, int k) {
    /* Perform shift logically */
    int xsrl = (unsigned) x >> k; 
    .
    .
    .
}

Надеюсь, теперь вы поняли вопрос.


person rushikesh.meharwade    schedule 27.07.2013    source источник
comment
Вам нужно будет сказать, что вы пробовали и что не сработало по сравнению с тем, что вы ожидали. В противном случае ваш вопрос будет закрыт.   -  person xaxxon    schedule 27.07.2013
comment
В чем у вас замешательство, может быть было бы лучше, если бы вы выложили собственно вопрос слово в слово из книги]   -  person aaronman    schedule 27.07.2013
comment
Извините за плохой вопрос, я только начал задавать вопросы о переполнении стека.   -  person rushikesh.meharwade    schedule 27.07.2013
comment
Хорошо, тогда я опубликую вопрос   -  person rushikesh.meharwade    schedule 27.07.2013
comment
понял, это совсем другой вопрос   -  person aaronman    schedule 27.07.2013
comment
извините, если я запутал вас, ребята, своим предыдущим вопросом   -  person rushikesh.meharwade    schedule 27.07.2013
comment
переполнение стека по-прежнему не делает за вас домашнее задание. Вам нужно задать конкретный технический вопрос. Вы еще ни одного не спросили. Ты будешь делать мою домашнюю работу за меня? не корректный вопрос. Опубликуйте, что вы пробовали, что вы ожидаете, и какая часть этого не делает то, что вы ожидаете.   -  person xaxxon    schedule 27.07.2013
comment
@xaxxon stackoverflow выполнит вашу работу только в том случае, если у кого-то будет много репутации   -  person aaronman    schedule 27.07.2013
comment
прочитайте оператор логического и арифметического сдвига присутствует в C, но концепция делает.   -  person Grijesh Chauhan    schedule 27.07.2013


Ответы (2)


Я не дам вам полный ответ, так как это, по-видимому, домашнее задание, но я дам вам несколько советов, которые помогут вам решить это самостоятельно:

  • для логического сдвига вправо на N бит нужно очистить верхние N бит результата после арифметического сдвига

  • вы можете очистить биты в значении, применив соответствующую маску, обычно используя побитовое И или XOR

  • чтобы очистить верхние N бит значения, вам нужна маска с N 0 и оставшимися битами 1

  • вы можете сгенерировать подходящую маску, используя сдвиг влево на W - N бит, где W — количество битов в слове (которое можно рассчитать как W = sizeof(int) * CHAR_BIT;)

Например. для логического сдвига вправо на 2

value              = 10001010
value >>= 2        = 11100010     // arithmetic right shift

mask               = 00111111     // mask has top 2 bits set to 0

value & mask       = 00100010     // apply mask to get logical right shift

Самая сложная часть — генерация маски, но если вы подумаете о смещении влево, применяемом для получения подходящего значения, за которым, возможно, следует еще одна побитовая операция, вскоре вы увидите довольно простое решение.

person Paul R    schedule 27.07.2013
comment
Спасибо за ваш ответ. - person rushikesh.meharwade; 27.07.2013
comment
Сейчас попробую сделать эту маску - person rushikesh.meharwade; 27.07.2013
comment
Разве это не должно быть сдвинуто на 2 !! - person I.Omar; 06.08.2018
comment
@Catch.Me: хороший улов - исправлено - спасибо! - person Paul R; 06.08.2018

Мне потребовалось немного времени, чтобы создать маску, предложенную Полом. Но я создал его следующим образом.

Сначала я оставил сдвиг 1 следующим образом

1 << (sizeof(int)*8-k);

Если я считаю, что k равно 10, а размер INT равен 32, я получу следующую маску

   00000000010000000000000000000000 ( 1 at 23 rd position 32 - 10 = 22 )

Затем добавьте его с -1 (0xffffffff)

   00000000010000000000000000000000
 + 11111111111111111111111111111111
 +++++++++++++++++++++++++++++++++++

   00000000001111111111111111111111 --> required mask with first 10 bits set to 

И с результатом арифметического сдвига даст результат логического сдвига.

Ниже приведен код C

unsigned srl(unsigned x, int k) {
/* Perform shift arithmetically */
        unsigned xsra = (int) x >> k;
    int mask = (1 << (sizeof(int)*8-k)) + -1;
    int result = xsra & mask;
}

И это работает.

person rushikesh.meharwade    schedule 27.07.2013