Правое смещение бит добавляет 1 к началу беззнакового целого в C - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь сдвинуть 16-битный адрес, чтобы получить идентификатор набора для симулятора кэша в C, но когда я пытаюсь сдвинуть бит вправо, я получаю дополнительную 1, прикрепленную к моему номеру.

У меня есть номер 0010100010011001. Затем я сдвигаюсь влево на 3 цифры, чтобы получить 0100010011001000. Пока все хорошо. Однако затем я пытаюсь сдвинуть вправо на 6 цифр и получить 0000010100010011 вместо 0000000100010011. Все мои целые числа без знака, и он добавляет только 1, когда я пытаюсь сместить.

Мой код для попытки сдвига следующий. В моем примере, tag_size равен 3, а b равно 6.

    unsigned int temp = addr << tag_size;
    unsigned int temp1 = temp >> b;
    unsigned int setid = temp1 >> tag_size;

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

16 бит int с сегодня не распространены. Вы можете попытаться определить переменную как short, которая обычно составляет 16 бит. Все зависит от машины, которую вы используете. Вы также можете использовать uint16, если вы ищете 16-битное целое число.

Похоже, проблема может быть в том, что используемый вами unsigned int на самом деле не 16 бит, как упомянул Кристиан Гиббонс в комментарии. Когда вы сдвигаете 0010100010011001 влево на 3 цифры, вы в конечном итоге получаете 10100010011001000, при этом самая левая 1 не удаляется, как вы ожидаете получить 16-битное целое число, тогда, когда вы снова сдвигаетесь вправо, вы получаете добавленную 1, которой не было ожидая.

Вы можете изменить свой код на это, и он должен работать так, как вы ожидали:

uint16_t temp = addr << tag_size;
uint16_t temp1 = temp >> b;
uint16_t setid = temp1 >> tag_size;
0 голосов
/ 09 апреля 2019

Вы должны использовать маску и выбрать интересующие вас биты;например:

unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int temp1 = temp >> b;
unsigned int setid = temp1 >> tag_size;

Если я понимаю, что вы ищете, то же самое можно сделать с помощью

unsigned int temp = addr & (0xffffu >> tag_size); // keep 16 low bits
unsigned int setid = temp >> b;

или

unsigned int temp = (addr << tag_size) & 0xffffu; // keep 16 low bits
unsigned int setid = temp >> (b + tag_size);

Это делает кодне зависит от размера unsigned int, который, как гарантирует C, составляет не менее 16 бит.

...