Логическое смещение вправо в C со значением ~ 0 - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть очень простой код, в котором логический сдвиг странным образом работает с ~ 0 значением

Насколько я знаю, он связан с типами данных со знаком / без знака

#include <stdio.h>

void printfbits(int x) {
    for (int i=7; i>=0;i--) {
        printf("%d", x>>i & 1);
    }
    printf("\n");
}

int main() {
    printfbits(~0>>1); 
}

Iожидайте 0111111, а не 1111111. Я также пытался, но безуспешно

printfbits(((unsigned int)~0)>>1);

Ответы [ 4 ]

0 голосов
/ 03 февраля 2019

Отрицание в ~0 произойдет с типом int.Но даже если вы сделаете ~(unsigned char)0, это все равно произойдет с типом int из-за неявного продвижения по службе.Следовательно, вы получите дополнительные 1-битные слева (обычно int имеет размер 32 бита (должен быть не менее 16)).Вы можете обрезать их, приведя результат bitnegation к uint8_t.

. Я бы также рекомендовал делать битовые операции на unsigned s (0 u, а не 0), так как семантика лучше стандартизированадля тех.

#include <stdio.h>
#include <stdint.h>

void printfbits(int x) {
    for (int i=7; i>=0;i--) {
        printf("%d", x>>i & 1);
    }
    printf("\n");
}

int main() {
    printfbits( (uint8_t)~0u >>1 );  //prints 01111111
}
0 голосов
/ 03 февраля 2019

Это сдвиг со знаком, который определяется реализацией.Но на большинстве 2 дополнительных машин:

enter image description here

0 голосов
/ 03 февраля 2019

Смещение вправо отрицательных значений со знаком равно , реализация определена Для gcc сдвигается 1, в противном случае сдвигается 0.

Вы были на правильном пути с броском, но это не помогает, так как функция все еще ожидает int.Вам нужно изменить функцию, чтобы она заняла unsigned char, и вы должны замаскировать все байты, кроме младшего, перед выполнением сдвига в вызове функции.

#include <stdio.h>

void printfbits(unsigned char x) {
    for (int i=7; i>=0;i--) {
        printf("%d", x>>i & 1);
    }
    printf("\n");
}

int main() {
    printfbits((~0u & 0xff)>>1);
}

Также обратите внимание на использование U суффикс константы 0. Это дает константе тип unsigned int.

0 голосов
/ 03 февраля 2019

На большинстве платформ int имеет длину 32 или 64 бита.Таким образом, вы сдвигаете более 8 бит вправо, в результате чего включается более 8 бит:

11...11111111 >> 1

становится:

11...11111111 // if sign extension happens
01...11111111 // if not

Как видите, независимо от того,Расширение знака происходит или нет, вы все равно увидите все 1 с, так как вы печатаете только младшие 8 бит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...