Установите старшие четыре бита значения int64 в c ++ - PullRequest
0 голосов
/ 08 июля 2019

У меня проблема с ++.Мне нужно изменить четыре старших бита значения int64.Старший бит должен быть «1», а следующие три бита должны быть «0».Остальное значение не должно быть изменено.

Можете ли вы помочь мне, пожалуйста.Спасибо

Ответы [ 4 ]

3 голосов
/ 08 июля 2019

Чтобы установить биты на 0, вы можете использовать битовое И с битовой маской:

    bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
AND 0000111111111111111111111111111111111111111111111111111111111111
--------------------------------------------------------------------
    0000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

Чтобы установить биты на 1, вы можете использовать битовое ИЛИ с битовой маской:

   0000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
OR 1000000000000000000000000000000000000000000000000000000000000000
-------------------------------------------------------------------
   1000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

Обратите внимание, что int64 является целым числом со знаком и является результатом изменения старшего значащего бита побитовым и / или имеет результат, определенный реализацией (на практике это означает, что значение зависит от того, как отрицательные числа представлены в системе).Битовые операции обычно выполняются только с беззнаковыми целыми числами.

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


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

uint64_t input = whatever;
input &= 0x0FFFFFFFFFFFFFFFu;
input |= 0x8000000000000000u;

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

using U = some_unsigned_integer;
U last_byte_offset = (sizeof(U) - 1) * 8;
U and_mask = ~(U(0xF0) << last_byte_offset);
U or_mask  =   U(0x80) << last_byte_offset;
0 голосов
/ 08 июля 2019

x = (x | 0x80000000) & 0x8fffffff ;

Первая часть, (x | 0x80000000), устанавливает старший бит в единицу. Вторая часть, & 0x8fffffff, устанавливает три следующих старших бита в ноль.

0 голосов
/ 08 июля 2019

Во-первых, нам нужна маска, которая равна 1 везде, кроме 4 старших бит:

int64 mask = ~ (int64(0xf) << 60);

Что мы сделали? 0xf - это двоичный код 00 ... 001111. Мы переместили двоичные цифры на 59 позиций влево, чтобы они стали 111100 ... 00, а затем все отрицали, чтобы получилось 000011 ... 11.

Обратите внимание на приведение к int64. Без него 0xf может быть 32-разрядным целым числом, а 0xf<<60 также является 32-разрядным (и его значением может быть что угодно).

Теперь очистите старшие 4 бита:

x = x & mask;

Но нам нужно, чтобы максимальный бит был равен 1. Для этого делайте поразрядно или с двоичным кодом 100 ... 00:

x = x | (int64(1) << 63);

Мы закончили.

0 голосов
/ 08 июля 2019

Сначала создайте маску для 3 битов:

0b0111 << 60

Затем используйте эту маску для очистки этих битов:

x &= ~((uint64_t)0b0111 << 60)

И, наконец, установите последний бит:

x |= ((uint64_t)1 << 63) 

На самом деле странно, что вам нужно редактировать биты со знаком 8 байтов, а не без знака.Возможно, у вас есть более глубокая проблема в вашем дизайне.


Исправлен этот недостаток int.

...