在内存中读写位(bit)

3

假设我有一个void*类型的内存地址,我需要打印出位于该内存地址中的位。我该如何做呢?

在我的处理器中,内存地址和内存值都是32位,int类型也是32位。因此,我考虑了以下方法:

unsigned int value = *memory_address;

然后通过简单的算术运算(一些moddiv操作)来获取保存在memory_address中的值的位。例如,value mod 2将给出该值的最后一位,依此类推。但从我所看到的(我原本期望不同的位),它并不起作用。有什么想法吗?

此外,是否有人知道现成的C源代码可以从内存中“读取/写入”位?


1
请提供更多的指示,说明您认为这个不起作用。 - Jens Gustedt
6个回答

7

将每个位的值向左移动一位,它与1相加

unsigned int value = *((unsigned int*)memory_address);
for( int i = 0; i < 32; i++)
{
    printf("%d ", value >> i & 1);
}

你也可以使用数学运算符来实现。你需要获取位值(2的位索引次幂)并在每次迭代中减去该值,以确保模数不会返回我们之前见过的值:

for( int i = 0; i < 32; i++)
{ 
    int bit_value = (int)pow(2,i + 1);
    int num_bit_value = value % bit_value; 
    printf("%d ", num_bit_value ? 1 : 0  );
    value -= num_bit_value;
}

1
好的,那似乎可以工作。但是你能解释一下为什么我的想法不行吗? - Johny

4
int main() {

  int a = 0xFFFF;

  void * v = &a; // v points to a

  int * aPtr = (int *) v; // aPtr also points to a

  int b = *aPtr; // b gets the value aPtr points to, aka a or 0xFFFF

  int aBit = (b >> 3) & 1; // aBit now contains bit 3 of the original a value

  // toggle the bit
  if (aBit) {
    b &= ~(1 << 3); // set bit 3 to 0
  } else {
    b |= (1 << 3); // set bit 3 to 1
  }

  *aPtr = b; // update original a
}

2

我发现将内存视为一个连续的字符字符串而不是一个空指针更容易理解。这样你可以访问任意数量的比特位。

以下是我的做法。

unsigned char
get_bit(char *array, int bit)
{
        int byte, k;
        byte = bit/8;
        k = 7 - bit % 8;
        return array[byte] & (1 << k);
}


void
set_bit(char *array, int bit, unsigned char value)
{
        int byte, k;
        byte = bit/8;
        k = 7 - bit % 8;
        if (value)
                array[byte] |= (1 << k);
        else
                array[byte] &= ~(1 << k);
}

0

这样怎么样:

bool isBit4Set = ((*someAddress) & 0x8 != 0);
(*someAddress) |= 0x8;   // Set bit 4

1
假设 someAddress 是一个指针类型,根据大小端可能会有所不同。 - Conrad Meyer
2
好的,它的名字已经强烈暗示了它是一个指针类型 :) - Ana Betts

0
bool getBit(void* data,int bit){ return ((*((int*)data)) & 1<<bit); }

void setBit(void* data,int bit,bool set){ if(set){ (*((int*)data)) |= 1<<bit; }else{ (*((int*)data)) &= ~(1<<bit);  } }

用于简单使用


0

打印字节和位的通用解决方案。

void dump_data(const void *object, size_t size)
{
  int i;
  printf("[ \n");
  for(i = 0; i < size; i++)
  {
    if (i%4 ==0)
    {
      printf("@%02X",&((const unsigned char *) object)[i]);
      printf("[ ");
    }
    printf("%02x ", ((const unsigned char *) object)[i] & 0xff);
    if ((i+1)%4 == 0)
      printf("]\n");
  }
  printf("]\n");

  printf("BINARY FORMAT\n");
  for (i = 0; i < size; i++)
  {
    printf("@%02X",&((const unsigned char *) object)[i]);
    printf("[ ");
    unsigned char value = (((unsigned char*)object)[i]);
    for(int j=0; j<8; j++)
      printf("%d ", (value & (0x80 >> j)) ? 1 : 0); // right shifting the value will print bits in reverse.
    printf("]\n");
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接