Поиск…


замечания

Операции сдвига бит не переносимы во всех архитектурах процессоров, разные процессоры могут иметь разную ширину бит. Другими словами, если вы написали

int a = ~0;
int b = a << 1;

Это значение будет отличаться на 64-битной машине против 32-битной машины или от процессора на базе x86 до процессора на базе PIC.

Endian-ness не нужно принимать во внимание сами бит-операции, т. Е. Правый сдвиг ( >> ) сдвигает биты в сторону младшего значащего бита, а XOR будет выполнять исключение или по битам. Endian-ness нужно учитывать только сами данные, то есть, если конечная точка является проблемой для вашего приложения, это вызывает беспокойство, независимо от бит-мудрейных операций.

& - побитовое И

int a = 6;     // 0110b  (0x06)
int b = 10;    // 1010b  (0x0A)
int c = a & b; // 0010b  (0x02)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Выход

a = 6, b = 10, c = 2

Зачем

Немного мудрый AND работает на уровне бит и использует следующую логическую таблицу истинности:

TRUE  AND TRUE  = TRUE
TRUE  AND FALSE = FALSE
FALSE AND FALSE = FALSE

Когда двоичное значение для ( a 0110 ) и бинарное значение b ( 1010 ) являются AND «эд вместе мы получим двоичное значение 0010 :

int a = 0 1 1 0
int b = 1 0 1 0 &
        ---------
int c = 0 0 1 0

Бит мудрый И не изменяет значения исходных значений, если специально не назначено использование битового умножения оператора-оператора &= :

int a = 5;  // 0101b  (0x05)
a &= 10;    // a = 0101b & 1010b

| - побитовое ИЛИ

int a = 5;     // 0101b  (0x05)
int b = 12;    // 1100b  (0x0C)
int c = a | b; // 1101b  (0x0D)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Выход

a = 5, b = 12, c = 13

Зачем

Бит мудрый OR работает на уровне бит и использует следующую таблицу логических истин:

true OR true = true
true OR false = true
false OR false = false

Когда двоичное значение для ( a 0101 ) и бинарное значение b ( 1100 ) являются OR «эд вместе мы получим двоичное значение 1101 :

int a = 0 1 0 1
int b = 1 1 0 0 |
        ---------
int c = 1 1 0 1

Бит мудрый ИЛИ не изменяет значения исходных значений, если только специально не назначено использование битового умножения оператора соединения |= :

int a = 5;  // 0101b  (0x05)
a |= 12;    // a = 0101b | 1101b

^ - побитовое XOR (исключающее ИЛИ)

int a = 5;     // 0101b  (0x05)
int b = 9;     // 1001b  (0x09)
int c = a ^ b; // 1100b  (0x0C)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

Выход

a = 5, b = 9, c = 12

Зачем

Немного мудрый XOR (эксклюзивный или) работает на уровне бит и использует следующую логическую таблицу истинности:

true OR true = false
true OR false = true
false OR false = false

Обратите внимание, что при операции XOR true OR true = false где, как и при действии true AND/OR true = true , следовательно, исключительный характер операции XOR.

Используя это, когда двоичное значение для ( a 0101 ) и бинарное значение b ( 1001 ) являются XOR - е изд «вместе мы получим двоичное значение 1100 :

int a = 0 1 0 1
int b = 1 0 0 1 ^
        ---------
int c = 1 1 0 0

Бит мудрый XOR не изменяет значения исходных значений, если специально не назначено использование битового оператора присваивания соединения ^= :

int a = 5;  // 0101b  (0x05)
a ^= 9;    // a = 0101b ^ 1001b

Бит мудрый XOR может использоваться многими способами и часто используется в операциях бит-маски для шифрования и сжатия.

Примечание . Следующий пример часто показан в качестве примера приятного трюка. Но не следует использовать в производственном коде (для достижения такого же результата лучше использовать std::swap() ).

Вы также можете использовать операцию XOR для замены двух переменных без временного:

int a = 42;
int b = 64;

// XOR swap
a ^= b;
b ^= a;
a ^= b;

std::cout << "a = " << a << ", b = " << b << "\n";

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

void doXORSwap(int& a, int& b)
{
    // Need to add a check to make sure you are not swapping the same
    // variable with itself. Otherwise it will zero the value.
    if (&a != &b)
    {
        // XOR swap
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

Таким образом, хотя это выглядит как хороший трюк в изоляции, он не полезен в реальном коде. xor не является базовой логической операцией, а комбинацией других: a ^ c = ~ (a & c) & (a | c)

также в 2015 году переменные компиляторов могут быть назначены как двоичные:

int cn=0b0111;

~ - побитовое NOT (унарное дополнение)

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)

std::cout << "a = " << static_cast<int>(a) <<
             ", b = " << static_cast<int>(b) << std::endl;

Выход

a = 234, b = 21

Зачем

Немного мудрый NOT (унарное дополнение) работает на уровне бит и просто переворачивает каждый бит. Если оно равно 1 , оно изменилось на 0 , если оно равно 0 , оно изменилось на 1 . Бит wise NOT имеет тот же эффект, что и XOR'ing значение против максимального значения для определенного типа:

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)
unsigned char c = a ^ ~0;

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

unsigned int i = ~0;
unsigned char c = ~0;

std::cout << "max uint = " << i << std::endl <<
             "max uchar = " << static_cast<short>(c) << std::endl;

Бит мудрый NOT не изменяет значение исходного значения и не имеет составного оператора присваивания, поэтому вы не можете сделать a ~= 10 например.

Бит мудрый NOT ( ~ ) не следует путать с логическим NOT ( ! ); где бит мудрый НЕ будет переворачивать каждый бит, логическое НЕ будет использовать все значение для его работы, другими словами (!1) != (~1)

<< - сдвиг влево

int a = 1;      // 0001b
int b = a << 1; // 0010b

std::cout << "a = " << a << ", b = " << b << std::endl;

Выход

a = 1, b = 2

Зачем

Левый бит мудрый сдвиг сдвинет биты значения левой руки ( a ) числа, указанного справа ( 1 ), по существу, заполняя младшие значащие биты 0, поэтому сдвиг значения 5 (двоичный 0000 0101 ) влево 4 раза (например, 5 << 4 ) даст значение 80 (двоичный 0101 0000 ). Вы можете заметить, что смещение значения влево 1 раз также совпадает с умножением значения на 2, например:

int a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a <<= 1;
}

a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a *= 2;
}

Но следует отметить, что операция сдвига влево сдвигает все биты влево, включая бит знака, например:

int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1;     // 1111 1111 1111 1111 1111 1111 1111 1110

std::cout << "a = " << a << ", b = " << b << std::endl;

Возможный выход: a = 2147483647, b = -2

В то время как некоторые компиляторы дают ожидаемые результаты, следует отметить, что если вы оставили сдвиг значного числа, чтобы повлиять на бит знака, результат не определен . Также не определено, если количество бит, которое вы хотите сдвинуть, является отрицательным числом или больше, чем количество бит, которое может удерживать тип слева, например:

int a = 1;
int b = a << -1;  // undefined behavior
char c = a << 20; // undefined behavior

Бит мудрый сдвиг влево не изменяет значения исходных значений, если специально не назначено использование битового оператора соединения соединения <<= :

int a = 5;  // 0101b
a <<= 1;    // a = a << 1;

>> - правая смена

int a = 2;      // 0010b
int b = a >> 1; // 0001b

std::cout << "a = " << a << ", b = " << b << std::endl;

Выход

a = 2, b = 1

Зачем

Правильный битовый сдвиг сдвигает биты значения левой руки ( a ) числа, указанного справа ( 1 ); следует отметить, что, хотя операция правого сдвига является стандартной, то, что происходит с битами правого сдвига по значению отрицательного числа, является определенной реализацией и, следовательно, не может быть гарантировано быть переносимым, например:

int a = -2;    
int b = a >> 1; // the value of b will be depend on the compiler

Также не определено, если количество бит, которое вы хотите сдвинуть, является отрицательным числом, например:

int a = 1;
int b = a >> -1;  // undefined behavior

Правильный сдвиг по битам не изменяет значения исходных значений, если специально не назначено использование битового оператора присваивания соединения >>= :

int a = 2;  // 0010b
a >>= 1;    // a = a >> 1;


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow