Было немного неловко следовать вашей логике, но после очистки младших битов в первом элементе и очистки старших битов в следующем, чтобы освободить место для битов, которые вы хотите установить, все, что вам нужно сделать, это сдвиг и ИЛИ ваши заменяющие биты для замены только что очищенных битов.
Например, с использованием вашей логики (с небольшим изменением имен переменных, чтобы было ясно, работаете ли вы с минимум или большинство значащих бит в элементе), вы можете сделать следующее:
void write_bits (unsigned *a, int off, unsigned v)
{
int elembits = (int)(sizeof *a) * CHAR_BIT, /* bits per element */
lsbits = elembits - off, /* lsb bits in current */
msbits = off - lsbits, /* msb bits in next */
cont_idx = off / (sizeof *a * CHAR_BIT);/* current index */
a[cont_idx] = a[cont_idx] >> lsbits; /* clear lsits in current */
a[cont_idx] = a[cont_idx] << lsbits;
a[cont_idx] |= (v >> msbits); /* set lsbits in current */
cont_idx++; /* advance to next element */
a[cont_idx] = a[cont_idx] << msbits; /* clear msbits in current */
a[cont_idx] = a[cont_idx] >> msbits;
a[cont_idx] |= ((v >> lsbits) << msbits); /* set msbits in current */
}
( примечание: вам нужно внимательно посмотретьпо вашей логике для определения cont_idx
и проверки, будет ли число заменяемых вами битов превышать sizeof (unsigned)
байт, влияющих на более чем два элемента, или же все биты, подлежащие замене, попадают в один элемент - который остаетсяВам)
Если коротко, например, использовать ваш тестовый пример, вы можете сделать:
#include <stdio.h>
#include <limits.h>
void write_bits (unsigned *a, int off, unsigned v)
{
int elembits = (int)(sizeof *a) * CHAR_BIT, /* bits per element */
lsbits = elembits - off, /* lsb bits in current */
msbits = off - lsbits, /* msb bits in next */
cont_idx = off / (sizeof *a * CHAR_BIT);/* current index */
a[cont_idx] = a[cont_idx] >> lsbits; /* clear lsits in current */
a[cont_idx] = a[cont_idx] << lsbits;
a[cont_idx] |= (v >> msbits); /* set lsbits in current */
cont_idx++; /* advance to next element */
a[cont_idx] = a[cont_idx] << msbits; /* clear msbits in current */
a[cont_idx] = a[cont_idx] >> msbits;
a[cont_idx] |= ((v >> lsbits) << msbits); /* set msbits in current */
}
int main (void) {
unsigned container[] = {0xAAAAAABB, 0xBBBBCCCC, 0xCCDDDDDD},
n = sizeof container / sizeof *container,
v = 0x444555;
write_bits (container, 24, v);
fputs ("unsigned container[] = {", stdout);
for (unsigned i = 0; i < n; i++)
printf (i ? ", 0x%08X" : "0x%08X", container[i]);
puts ("};");
}
Пример использования / Вывод
$ ./bin/arr-write-bits
unsigned container[] = {0xAAAAAA44, 0x4555CCCC, 0xCCDDDDDD};