Выключатель KnR 2-8: поверните число вправо. Это нормально?

76
5

Я следую за KnR. Это упражнение 2-8. В нем говорится создать функцию для поворота числа вправо на некоторое количество бит.

Ответ, который я придумал, "кажется", выполняет эту работу и в двух строках. Тем не менее, я проверял другие методы в Интернете. В этом ответе SO говорится о смещении каждого бита по одному. Что не так, если я перемещаюсь навалом (как в моем коде ниже)? есть что-то, чего я не хватает?

#include <stdio.h>

/* Rotate number 'num' to the right by 'rbits' bits */

int RotRight(unsigned int num,int rbits){

unsigned int mask = num << ((sizeof(int)*8)-rbits);
return (num>>rbits)|mask;
}

EDIT: чтобы учесть то, что я узнал из комментариев, вот отредактированная версия вышеуказанного кода. Это хорошо выглядит?

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int RotRight(int num,int rbits){

if(num<0) {
fprintf(stderr,"Rotating negative numbers is undefined\n");
exit(EXIT_FAILURE);
}

if(rbits >= sizeof(int)*CHAR_BIT) rbits = rbits % (sizeof(int)*CHAR_BIT);
if(rbits<=0) return num; // rbit range should be 0 to (bitwidth - 1)

unsigned int mask = num << ((sizeof(int)*CHAR_BIT)-rbits);
return (num>>rbits)|mask;
}

спросил(а) 2021-01-25T11:42:52+03:00 4 месяца, 3 недели назад
1
Решение
63

1-е издание кода было хорошим, но вторая версия становится слишком сложной. Предложите использовать беззнаковые числа для упрощения.

Поскольку код вращает биты, вращение ширины N раз-бит такое же, как при вращении 0. IOW, нам нужно использовать только наименее значимые бит счетчика сдвига.

#include <stdio.h>
#include <limits.h>

/* Rotate number 'num' to the right by 'rbits' bits */

unsigned RotRight(unsigned num, unsigned rbits) {
#define BIT_WIDTH (CHAR_BIT * sizeof num)
#define RBIT_MASK (BIT_WIDTH - 1)
rbits %= BIT_WIDTH; // compiler likely to change this to rbits &= RBIT_MASK;
unsigned mask = num << ((BIT_WIDTH - rbits) % BIT_WIDTH);
return (num >> rbits) | mask;
}

ответил(а) 2021-01-25T11:42:52+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема