从内存c ++中读取位,移位并存储

时间:2018-07-01 00:55:36

标签: c++ memory bit-manipulation bit-shift

我希望从内存中读取16位,在任何方向上将它们移位n次,然后再保存到相同的内存位置。

假设在内存位置0xfffaaa中,我有: 0101111101100001,我想将它向右移动一次(>>1) 因此,我声明了一个指向uint16_t的{​​{1}}变量。

转换后,该变量包含: 0xfffaaa(十进制的24417)。 右移后: 0110000101011111 1->丢失。 存储在内存中的是: 0011000010101111,而不是: 1010111100110000 1 --->丢失。

这是我尝试执行此操作的示例。

0010111110110000

控制台输出为:

#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;
}

我该如何使用uint16_t进行工作?

3 个答案:

答案 0 :(得分:0)

问题不在于转变,而在于从位图获取数据的方式。

由于右移会将位从位图[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);

答案 1 :(得分:0)

要知道一种方法是否确实更快,则必须运行探查器。

有两种方法可以解决您的问题(如果您不包括在位图中交换数据的可能性)。

  1. 就像@ 1201ProgramAlarm一样:

    //获取该指针 uint16_t * p16 =(uint16_t *)位图; uint16_t v(* p16); v =(v >> 8)| (v << 8); //交换 v >> = 1; * p16 =(v >> 8)| (v << 8); //交换回以保存为位图

这可以用几种不同的方式编写,您甚至可以将转换内容并入交换中:

v = (v >> 9) | (v << 7);
  1. 您不使用p16指针

由于您可以同时进行交换和移位,因此也可以直接使用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一样快。

答案 2 :(得分:0)

您可以有效地使用并集:

#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