问题描述
提取并修改位
从打包的final_value中的某个位置中选择n个位数,然后写入任意位置,而无需修改uint16_t test_bit = 0x3048的原始内容。
预期输出= 0x5048
例如:从final_val中选择010(从位置17开始的3bits )并写入任意位置(位置11 )
0x3048 = 01 11 0 000 0100 1000;
0x5048 = 01 01 0 000 0100 1000
一些示例:
示例A:
粗体是提取的。我们从Val_1中提取位0到7,并仅替换Val_2中的位0到7,而未修改位8到15。
Val_1 0x1b7 0000 0001 1011 0111
Val_2 0x27b7 0010 0111 1011 0111
示例B:
从Val1中提取3位[从8位到10位],并替换Val_2中的3位[从11位至13位]。
Val_1 0x129 0000 0 001 0010 1001
Val_2 0x4C48 01 00 1 100 0100 1000
到目前为止尝试过:
#include <stdio.h>
#include <stdint.h>
void read_and_write(uint32_t* final_val,uint16_t* write_val,uint8_t start_pos,uint8_t end_pos)
{
uint32_t temp = *final_val;
*write_val = (uint16_t) ((temp >> start_pos) & ((1 << end_pos) - 1)); // store the desired number of bits in write_val
*final_val = (temp >> end_pos); //shift final_val by end_pos since those bits are already written
printf("\n temp %x,write_val %x,final_val %x ",temp,*write_val,*final_val);
}
void main()
{
uint32_t final_val = 0x0; //Stores 20 extracted bits from val1,val2 and val3 into final_val (LSB to MSB in order)
uint16_t ext_val1 = 0x80;
uint8_t ext_val2 = 0x0;
uint8_t ext_val3 = 0x2;
final_val = (ext_val1 | (ext_val2 << 9) | (ext_val3 << 17));
printf ("\n final_val %x",final_val);
uint16_t data_1,data_2,data_3,write_val1,write_val2,write_val3;
// Read first 9 bits of final_val and write only into [0:9] position of existing data_1
uint8_t start_pos = 0;
uint8_t end_pos = 9;
data_1 = 0x80;
read_and_write(&final_val,&write_val1,start_pos,end_pos);
write_val1 = write_val1 | data_1;
// Read next 8 bits of final_val and write only into [0:8] position of existing data_2
start_pos = 0;
end_pos = 8;
data_2 = 0x27b7;
read_and_write(&final_val,&write_val2,end_pos);
write_val2 = write_val2 | data_2;
//Read next 3 bits of final_val and write only into[13:11] position of existing data_3
start_pos = 11;
end_pos = 13;
data_3 = 0x3048;
read_and_write(&final_val,&write_val3,end_pos);
write_val3 = write_val3 | data_3;
printf ("\n val1 0x%x val2 0x%x val3 0x%x final_val 0x%x",ext_val3,final_val);
}
解决方法
这是带有帮助程序功能和测试框架的简单实现:
-
((uint32_t)1 << n) - 1
计算设置了低n
位的二进制数2 n -1。 -
uint32_t mask = (((uint32_t)1 << n) - 1) << pos2;
计算mask
位,n
位的位置为pos2
。 -
(val2 & ~mask)
清除n
位置pos2
处的val2
位,而其他位保持不变。 -
extract(val1,pos1,n) << pos2
将从n
提取的val1
位移动到位置pos2
,其他位为0
。 - 对这些值进行或运算以计算预期结果,从
n
中的位置val1
开始复制pos2
中的val2
位。
代码如下:
#include <stdio.h>
#include <stdint.h>
uint32_t extract(uint32_t data,int pos,int n) {
return (data >> pos) & (((uint32_t)1 << n) - 1);
}
uint32_t replace(uint32_t val1,uint32_t val2,int pos1,int n,int pos2) {
uint32_t mask = (((uint32_t)1 << n) - 1) << pos2;
return (val2 & ~mask) | (extract(val1,n) << pos2);
}
void test(uint32_t val1,int pos2) {
uint32_t res = replace(val1,val2,n,pos2);
printf("extracting bits [%d-%d] from 0x%04X to bits [%d-%d] in 0x%04X -> 0x%04X\n",pos1 + n - 1,val1,pos2,pos2 + n - 1,res);
}
int main() {
test(0x1234,0x7048,1,3,11);
test(0x01b7,0x2743,8,0);
test(0x0129,0x7448,11);
return 0;
}
输出:
extracting bits [1-3] from 0x1234 to bits [11-13] in 0x7048 -> 0x5048
extracting bits [0-7] from 0x01B7 to bits [0-7] in 0x2743 -> 0x27B7
extracting bits [8-10] from 0x0129 to bits [11-13] in 0x7448 -> 0x4C48
,
这里具有提取特定位的值并将其替换为从另一个值提取的值的功能。
uint32_t extract(uint32_t read_data,int n_bits,int pos)
{
uint32_t mask = (n_bits < (CHAR_BIT * sizeof(mask) - 1)) ? ((1LU << n_bits) - 1) << pos : -1;
return (mask & read_data) >> pos;
}
uint32_t replace(uint32_t read_val,uint32_t write_val,int read_pos,int write_pos,int n_bits)
{
uint32_t extracted = extract(read_val,n_bits,read_pos);
uint32_t mask = (n_bits < (CHAR_BIT * sizeof(mask) - 1)) ? ((1LU << n_bits) - 1) << write_pos : -1;
write_val &= ~mask;
write_val |= extracted << write_pos;
return write_val;
}
int main (void)
{
uint32_t val = 0x1234;
uint32_t val2 = 0xabcd;
printf("%x\n",extract(val,4,8));
printf("%x\n",replace(val,4));
}