从内存 C++ 中读取位,移位并存储
Read bits from memory c++, shift and store
我想从内存中读取 16 位,将它们在任何方向上移动 n 次,然后保存回相同的内存位置..
假设在内存位置 0xfffaaa
我有:
0101111101100001
我想将它向右移动一次 (>>1
)
所以我声明了一个指向 0xfffaaa
的 uint16_t
变量。
转换后,该变量包含:
0110000101011111
(十进制为 24417)。
右移后:
0011000010101111
1 --> 丢失位。
存储在内存中的是:
1010111100110000
而不是:
0010111110110000
1---> 丢失位。
这是我如何尝试做的一个例子..
#include <bitset>
#include <iostream>
using namespace std;
int main(){
volatile uint8_t *bitmap = (uint8_t *)malloc(2);
bitmap[0] = 0b01011111;
bitmap[1] = 0b01100001;
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n' << '\n';
uint16_t* p16 = (uint16_t*)bitmap;
cout << bitset<16>(p16[0]) << '\n';
p16[0]>>=1;
cout << bitset<16>(p16[0]) << '\n' << '\n';
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n';
return 0;
}
控制台输出为:
0101111101100001
0110000101011111
0011000010101111
1010111100110000
如何才能按我希望的方式进行位移 uint16_t?
问题不在于移位,而在于如何从位图中获取数据。
由于右移会将位从位图[0]移动到位图[1],您可以使用乘法将数据提取到更大的类型中:
auto v16 = 256 * bitmap[0] | bitmap[1];
v16 >>= 1;
bitmap[0] = uint8_t(v16 / 256);
bitmap[1] = uint8_t(v16 & 255);
或者,仅使用移位操作:
auto v16 = (bitmap[0] << 8) + bitmap[1];
v16 >>= 1;
bitmap[0] = uint8_t(v16 >> 8);
bitmap[1] = uint8_t(v16 & 0xFF);
要知道它是否确实更快,您必须 运行 一个分析器。
有两种方法可以解决您的问题(如果您不包括在位图中交换数据的可能性。)
喜欢@1201ProgramAlarm 说:
// 得到那个指针
uint16_t* p16 = (uint16_t*)位图;
uint16_tv(*p16);
v = (v >> 8) | (v << 8); // 交换
v >>= 1;
*p16 = (v >> 8) | (v << 8); // 交换回来保存在位图中
这可以用几种不同的方式编写,您甚至可以将转换合并到交换中:
v = (v >> 9) | (v << 7);
- 您没有使用 p16 指针
既然swap和shift可以同时进行,那你也可以直接用你的p8:
uint61_t v((bitmap[1] >> 9) | (bitmap[0] << 7));
bitmap[0] = v >> 8;
bitmap[1] = v; // C auto-and (i.e. (v & 0xFF) is not required)
请注意,您无法优化更多,因为当您修改位图时,您无法在修改后重新加载数据。小心那个。
现在,汇编中的这个会像这样优化,虽然它可能不是最快的(有时当你让 C/C++ 编译器做它的优化工作时会有惊喜!)
mov ax, [ep] ; get current value (16 bits)
xchg al, ah
shr ax, 1 ; shift by one unsigned
xchg al, ah
mov [ep], ax ; save result
对于 32 位和 64 位,在 x86 中有一个 swapb
指令(在 64 位中也是如此)。
请注意,一次读取和写入一个字节可能与读取 16 位和 xchg
-ing 一样快。
您可以有效地使用 union:
#include <bitset>
#include <iostream>
#include <algorithm>
using namespace std;
union joinbits
{
uint16_t data;
uint8_t bits[2];
};
int main(){
volatile uint8_t *bitmap = (uint8_t *)malloc(2);
bitmap[0] = 0b01011111;
bitmap[1] = 0b01100001;
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n' << '\n';
joinbits j;
j.bits[1] = bitmap[0];
j.bits[0] = bitmap[1];
j.data >>= 1;
bitmap[0] = j.bits[1];
bitmap[1] = j.bits[0];
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n';
return 0;
}
输出为:
0101111101100001
0010111110110000
我想从内存中读取 16 位,将它们在任何方向上移动 n 次,然后保存回相同的内存位置..
假设在内存位置 0xfffaaa
我有:
0101111101100001
我想将它向右移动一次 (>>1
)
所以我声明了一个指向 0xfffaaa
的 uint16_t
变量。
转换后,该变量包含:
0110000101011111
(十进制为 24417)。
右移后:
0011000010101111
1 --> 丢失位。
存储在内存中的是:
1010111100110000
而不是:
0010111110110000
1---> 丢失位。
这是我如何尝试做的一个例子..
#include <bitset>
#include <iostream>
using namespace std;
int main(){
volatile uint8_t *bitmap = (uint8_t *)malloc(2);
bitmap[0] = 0b01011111;
bitmap[1] = 0b01100001;
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n' << '\n';
uint16_t* p16 = (uint16_t*)bitmap;
cout << bitset<16>(p16[0]) << '\n';
p16[0]>>=1;
cout << bitset<16>(p16[0]) << '\n' << '\n';
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n';
return 0;
}
控制台输出为:
0101111101100001
0110000101011111
0011000010101111
1010111100110000
如何才能按我希望的方式进行位移 uint16_t?
问题不在于移位,而在于如何从位图中获取数据。
由于右移会将位从位图[0]移动到位图[1],您可以使用乘法将数据提取到更大的类型中:
auto v16 = 256 * bitmap[0] | bitmap[1];
v16 >>= 1;
bitmap[0] = uint8_t(v16 / 256);
bitmap[1] = uint8_t(v16 & 255);
或者,仅使用移位操作:
auto v16 = (bitmap[0] << 8) + bitmap[1];
v16 >>= 1;
bitmap[0] = uint8_t(v16 >> 8);
bitmap[1] = uint8_t(v16 & 0xFF);
要知道它是否确实更快,您必须 运行 一个分析器。
有两种方法可以解决您的问题(如果您不包括在位图中交换数据的可能性。)
喜欢@1201ProgramAlarm 说:
// 得到那个指针 uint16_t* p16 = (uint16_t*)位图; uint16_tv(*p16); v = (v >> 8) | (v << 8); // 交换 v >>= 1; *p16 = (v >> 8) | (v << 8); // 交换回来保存在位图中
这可以用几种不同的方式编写,您甚至可以将转换合并到交换中:
v = (v >> 9) | (v << 7);
- 您没有使用 p16 指针
既然swap和shift可以同时进行,那你也可以直接用你的p8:
uint61_t v((bitmap[1] >> 9) | (bitmap[0] << 7));
bitmap[0] = v >> 8;
bitmap[1] = v; // C auto-and (i.e. (v & 0xFF) is not required)
请注意,您无法优化更多,因为当您修改位图时,您无法在修改后重新加载数据。小心那个。
现在,汇编中的这个会像这样优化,虽然它可能不是最快的(有时当你让 C/C++ 编译器做它的优化工作时会有惊喜!)
mov ax, [ep] ; get current value (16 bits)
xchg al, ah
shr ax, 1 ; shift by one unsigned
xchg al, ah
mov [ep], ax ; save result
对于 32 位和 64 位,在 x86 中有一个 swapb
指令(在 64 位中也是如此)。
请注意,一次读取和写入一个字节可能与读取 16 位和 xchg
-ing 一样快。
您可以有效地使用 union:
#include <bitset>
#include <iostream>
#include <algorithm>
using namespace std;
union joinbits
{
uint16_t data;
uint8_t bits[2];
};
int main(){
volatile uint8_t *bitmap = (uint8_t *)malloc(2);
bitmap[0] = 0b01011111;
bitmap[1] = 0b01100001;
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n' << '\n';
joinbits j;
j.bits[1] = bitmap[0];
j.bits[0] = bitmap[1];
j.data >>= 1;
bitmap[0] = j.bits[1];
bitmap[1] = j.bits[0];
cout << bitset<8>(bitmap[0]);
cout << bitset<8>(bitmap[1]) << '\n';
return 0;
}
输出为:
0101111101100001
0010111110110000