Печать бит Часть III


Последний вопрос я играл вокруг С-это правый поворот. Я думаю, что это тоже называется "бочку". Пожалуйста, напишите, если у вас есть лучшее решение, пожалуйста, пост. Я все еще учусь искусство битовые операции.

/*
 * Next write a function rightrot(x,n) that returns the value of the
 * integer x rotated to the right by n bit positions
 *
 * build with:
 *   gcc -o bit_twiddle -Wall -g -lm ./bit_twiddle.c
 */

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

size_t size_of_int = sizeof(int) << 3;

void printbits(unsigned x) {
    unsigned mask = 1 << (size_of_int - 1);
    int i = 0;
    for(i = 1; i <= size_of_int; ++i, x <<= 1) {
       ((x & mask) == 0) ? printf("0") : printf("1");
       (((i % 4))==0) ? printf(" ") : printf("%s","");
    }
    printf("\n");
}

void rightrot(unsigned x, unsigned n) {
    printf("%15s =", "rightrot"); printbits((((~(~0 << n)) & x) << (size_of_int - n)) | (x >> n));
}

int main(int argc, char *argv[]) {
    unsigned input=4042322167, nbits=4;
    printf("%15s =", "x"); printbits(input);
    rightrot(input, nbits);
    return(0);
}


401
3
задан 18 ноября 2011 в 06:11 Источник Поделиться
Комментарии
1 ответ

Что это должно быть?

size_t size_of_int = sizeof(int) << 3;

Сдвиг влево на 3 очень загадочно. Умножаем на 8 или объяснить, что вы делаете. Но лучше всего будет, чтобы умножить число байт фактическим битов в байте.

Если вы хотите, чтобы количество битов в целое число:

#include <climits>
size_t size_of_int = sizeof(int) * CHAR_BIT;;

PrintBits()

Люди больше привыкли видеть в цикле от 0:

for(i = 1; i <= size_of_int; ++i, x <<= 1)

// So prefer to loop from zero

for(i = 0; i < size_of_int; ++i, x <<= 1)

Это уродливый способ печати 0/1

((x & mask) == 0) ? printf("0") : printf("1");

Только одна печать: затем использовать выражения, чтобы решить, что печатать:
Выражение (х & маска) == 0 - это перебор, если равен нулю, то это уже ложь.

printf("%d", (x & mask) ? 1 : 0);

Опять уродливый способ печати пространство каждые четыре места:

(((i % 4))==0) ? printf(" ") : printf("%s","");

// Personally I would just use an if

if (i%4==0) { printf(" ");}


  • Результат действительно пустота? Что произойдет, если какие-либо функции printf() заявления у вас использовать не получится. В действительности вы должны проверять коды возврата функции, вызов и обработку ошибки или передачи ошибка обратно для них, чтобы справиться.

  • Ваша функция печати очень ограничен и только печатает в stdout. Вы должны действительно сделать версию, которая выводит в поток

Объявления функций должны быть:

int printbits(unsigned x) {return fprintbits(stdout, x);}
int fprintbits(FILE*, unsigned x)
{
// Code Here
}

RightRot()

Почему вы printbits callint() от rightrot()? Функция должна делать одно задание, и это повернуть биты. Если вы хотите, чтобы распечатать результат в порядке. Но эта функция не должна делать печать.


  • Так что вам нужно изменить вашу подпись, так что она может возвращать результат

Рефакторинг

unsigned rightrot(unsigned x, unsigned n)


  • Делаем все на одной линии. Просто делает код нечитаемым. Разделить его вверх. Один оператор в строке. Никто не даст дополнительных баллов для написания сжатого кода (но они подарят вам знаки для написания ясного кода)

Рефакторинг:

 return ((((~(~0 << n)) & x) << (size_of_int - n)) | (x >> n));

Даже после удаления всех плевел эту строку по-прежнему нечитабельны. Разбить его на несколько инструкций, и использовать Вэнс. Таким образом, вы можете комментировать происходящее. Это не так, если одна строка является более эффективным. Компилятор будет удалить все неиспользуемые Вэнс.

 // Shift right. Note: We loose bottom n bits (these need to be recovered.
unsigned base = x >> n;

// Create a mask for the bottom n bits.
unsigned mask = (~(~0 << n));

// Move the bottom n bits to the top of integer (as if they had wrapped around:
unsigned wrap = (x & mask) << (size_of_int - n);

return wrap | base;

Теперь мы можем читать то, что происходит. Мы видим, что создав маску можно сделать более четко.

 unsigned  mask  = (1 << n) - 1;

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

 unsigned  wrap = x << (size_of_int - n);

Также обратите внимание, что если N >= size_of_int вы собираетесь остаться с нулем. Поэтому первое, что вы должны сделать, это убедиться, что N находится в правильном диапазоне. Давайте предположим, что значение больше, будет просто обернуть вокруг несколько раз.

// Multiple wraps do not add anything.
n = n % size_of_int;

Использования (из основных)

fprintbits(stdout, rightrot(input, nbits));

3
ответ дан 19 ноября 2011 в 04:11 Источник Поделиться