从8位数据中去除C中的奇偶校验位,然后是1个奇偶校验位

时间:2012-06-11 10:16:24

标签: c parity

我有一个8位数据的位缓冲区,后跟1个奇偶校验位。这种模式重演。缓冲区当前存储为八位字节数组。

示例(p是奇偶校验位):

0001 0001 p000 0100 0p00 0001 00p01 1100 ...

应该成为

0001 0001 0000 1000 0000 0100 0111 00 ...

基本上,我需要剥离每第9位才能获得数据位。我怎样才能做到这一点?

这与another question在某个时候提到的问题有关。

这是在32位机器上,因此相关问题的解决方案可能不适用。最大可能的比特数是45,即5个数据八位字节

这是我到目前为止所尝试的。我创建了一个“布尔”数组,并根据八位字节的位集将这些位添加到数组中。然后我查看数组的每个第九个索引并通过它。然后将剩余的数组向下移动一个索引。然后我只剩下数据位。我在想可能有更好的方法来做到这一点。

4 个答案:

答案 0 :(得分:2)

在伪代码中(因为你没有提供任何证明你已尝试过的东西),为了简单起见,我可能会这样做:

  • 查看数据(包括奇偶校验位)作为位流
  • 虽然还有一些内容需要阅读:
    • 阅读接下来的8位
    • 写入输出
    • 再读一遍,丢弃它

这让你“担心”读取字节,这不再是一个有用的操作,因为你的字节与想要丢弃的位交错。

答案 1 :(得分:2)

你有一个位数组的想法是好的。只需用32位数字(缓冲区)实现位数组。

从缓冲区中间删除一位:

void remove_bit(uint32_t* buffer, int* occupancy, int pos)
{
    assert(*occupancy > 0);
    uint32_t high_half = *buffer >> pos >> 1;
    uint32_t low_half = *buffer << (32 - pos) >> (32 - pos);
    *buffer = high_half | low_half;
    --*occupancy;
}

向缓冲区添加一个字节:

void add_byte(uint32_t* buffer, int* occupancy, uint8_t byte)
{
    assert(*occupancy <= 24);
    *buffer = (*buffer << 8) | byte;
    *occupancy += 8;
}

从缓冲区中删除一个字节:

uint8_t remove_byte(uint32_t* buffer, int* occupancy)
{
    uint8_t result = *buffer >> (*occupancy - 8);
    assert(*occupancy >= 8);
    *occupancy -= 8;
    return result;
}

您必须安排调用,以便缓冲区永不溢出。例如:

buffer = 0;
occupancy = 0;
add_byte(buffer, occupancy, *input++);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 7);
*output++ = remove_byte(buffer, occupancy);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 6);
*output++ = remove_byte(buffer, occupancy);
... (there are only 6 input bytes, so this should be easy)

答案 2 :(得分:1)

我编写了辅助函数来读取未对齐的位缓冲区(这适用于AVC流,请参阅原始源here)。代码本身就是GPL,我在这里粘贴了有趣的(修改过的)位。

typedef struct bit_buffer_ {
  uint8_t * start;
  size_t size;
  uint8_t * current;
  uint8_t read_bits;
} bit_buffer;

/* reads one bit and returns its value as a 8-bit integer */
uint8_t get_bit(bit_buffer * bb) {
  uint8_t ret;
  ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
  if (bb->read_bits == 7) {
      bb->read_bits = 0;
      bb->current++;
  }
  else {
      bb->read_bits++;
  }
  return ret;
}

/* reads up to 32 bits and returns the value as a 32-bit integer */
uint32_t get_bits(bit_buffer * bb, size_t nbits) {
  uint32_t i, ret;
  ret = 0;
  for (i = 0; i < nbits; i++) {
    ret = (ret << 1) + get_bit(bb);
  }
  return ret;
}

您可以使用以下结构:

uint_8 * buffer;
size_t buffer_size;
/* assumes buffer points to your data */

bit_buffer bb;
bb.start = buffer;
bb.size = buffer_size;
bb.current = buffer;
bb.read_bits = 0;

uint32_t value = get_bits(&bb, 8);
uint8_t parity = get_bit(&bb);

uint32_t value2 = get_bits(&bb, 8);
uint8_t parity2 = get_bit(&bb);

/* etc */

我必须强调这段代码是完全可靠的,必须实现正确的绑定检查,但它在我的用例中工作正常。

我把它作为练习留给你来实现一个适当的位缓冲读取器,用它作为灵感。

答案 3 :(得分:1)

这也有效

void RemoveParity(unsigned char buffer[], int size)
{
    int offset = 0;
    int j = 0;

    for(int i = 1; i + j < size; i++)
    {
        if (offset == 0)
        {
            printf("%u\n", buffer[i + j - 1]);
        }
        else
        {
            unsigned char left = buffer[i + j - 1] << offset;
            unsigned char right = buffer[i + j] >> (8 - offset);
            printf("%u\n", (unsigned char)(left | right));
        }
        offset++;
        if (offset == 8)
        {
            offset = 0;
            j++; // advance buffer (8 parity bit consumed)
        }
    }
}