Как проще всего переписать биты 10, 11, 12 беззнакового целого в X? - PullRequest
0 голосов
/ 24 июня 2019

Пусть val и x - 32-разрядные целые числа без знака.Пусть x будет в диапазоне от 0 до 8 (таким образом, не более 3 бит).Как проще всего переписать биты 10, 11 и 12 в val, чтобы они соответствовали битам x?Т.е. таким образом, что (val >> 10) & 1 == x & 1, (val >> 11) & 1 == (x >> 1) & 1 и (val >> 12) & 1 == (x >> 2) & 1?Например, это выражение выполняет это:

(val & ~(0x7 << 10)) | (x << 10)

Можно ли выполнить то же самое с меньшим количеством операций?

Ответы [ 2 ]

2 голосов
/ 24 июня 2019

Выражение, которое вы используете, является самым простым способом (хотя у меня нет доказательств), предполагая, что val и x являются переменными, а не константами.Конечно, любой приличный компилятор будет вычислять постоянное значение ~(0x7 << 10) во время компиляции.

Возможно, вы захотите избежать дублирования, написав (встроенную) функцию или макрос, если вам это нужно много.

1 голос
/ 24 июня 2019

Если x равно uint8_t и val равно uint32_t, то я бы сделал это

val &= ~(0b111 << 10); // clear current value
val |= (x << 10);      // set new value

Обобщение как функция

void overwriteValue(uint32_t * val, uint8_t * x, uint8_t bit_shift, uint8_t bit_mask){
    *val &= ~(bit_mask << bit_shift);
    *val |= (*x << bit_shift);
}

Пример:

uint32_t my_val = 0xafaf11af; //0b1010111110101111000 100 0110101111
                              //                bits 12, 11, 10
uint8_t x = 0x3;
uint8_t bs = 10;
uint8_t bm = 0x7;
overwriteValue(&my_val, &x, bs, bm);
//my_val = 0xafaf0daf
//0b1010111110101111000 011 0110101111
//                bits 12, 11, 10
...