Прежде всего, нет, это не моя домашняя работа, это лаборатория, которую дала книга под названием «Компьютерные системы: взгляд программиста» (кстати, отличная книга)
Мне нужно выполнить логический сдвиг вправо на целые числа со знаком, не используя следующие:
Разрешенные операторы:
! + ~ | >> << ^
Что я пробовал до сих пор?
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
int mask = ~0;
int shiftAmount = 31 + ((~n)+1);//this evaluates to 31 - n on two's complement machines
mask = mask << shiftAmount;
mask = ~mask;//If n equals 0, it means we have negated all bits and hence have mask = 0
x = x >> n;
return x & mask;
}
Это работает просто отлично, если n не равно 0, когда это делает этот код, обрывается, потому что маска превратится во все 0 и функция вернет 0.
Я был бы признателен за любую подсказку в правильном направлении, а не полный код.
Опять же, это не домашняя работа; лабораторные задания находятся в открытом доступе здесь http://csapp.cs.cmu.edu/public/labs.html
P.S Не дублировать, не публиковать решения, которые включают приведение к неподписанному и затем смещение.
Вы можете сделать маску таким образом:
int mask = 1 << shiftAmount;
mask |= mask - 1;
Что по сравнению с другим подходом, как это
this approach | other approach
can have 0 bits set : no | yes
can have 32 bits set: yes | no
Я знаю, что немного опоздал, но думаю, что лучший способ — сделать что-то вроде этого:
int logicalShift(int x, int n) {
int mask = ( 1 << sizeof(int) - n ) - 1;
return x >> n & mask;
}
Маска устанавливает самый верхний n
биты в 0.
Конечно, это можно записать как:
int logicalShift(int x, int n) {
return x >> n & ( 1 << sizeof(int) - n ) - 1;
}
Но компилятор, вероятно, поймет, как оптимизировать первый.