每个位操作都可操作缓冲区中的数据,缓冲区由无符号字符作为指针来指定。该指针指向足够多的字节来表示缓冲区中的位数。如果缓冲区中的位数不是8的倍数,那么说明最后一个字节的某些位没有使用。
bit_get
bit_get 操作获取缓冲区中一个位的状态。要做到这一点,首先要确定位所在的字节,然后通过一个掩码从字节中获取相应的位。掩码中设置为1的位是将要从字节中读出的位。接着用一个循环操作将位移动到适当的位置。通过索引bits中相应的字节,并应用掩码,可以获取所需的位。
bit_get的时间复杂度为O(1)。这是因为获取缓冲区中位的状态所进行的所有操作都能够在固定时间内完成。
bit_set
bit_set 操作设置缓冲区中一个位的状态。此操作与bit_get的工作方式相 似,只是它是利用掩码设置指定位的状态,而获取指定位的状态。
bit_set 的时间复杂度为O(1)。这是因为获取缓冲区中位的状态所进行的所有操作都能够 在固定时间内完成。
bit_xor
对两个缓冲区bits1和bits2进行按位异或运算,并将计算的结果放到缓冲区bitsx中。要做到这一点,将bits1中第i个位置的位与bits2中第i个位置的位进行比较,如果位值相同,将第i个位置的位置0;否则,将第i个位置的位置1。这个过程会持续下去直到size指定的每个缓冲区中的位都计算完成。
bit_xor 的时间复杂度为O(β),其中β是每个缓冲区中的位数。这是因为此操作要在毎个位上循环迭代一次。
bit_rot_left
bit_rot_left 将缓冲区指定数量的位向左轮转。首先保存最左端字节的最左端位值,然后向左一位一位地移动每个字节的位值。在移动字节的过程中,将前一个字节最右边的位移到当前字节的最左边。当处理到最后一个字节时,将其最右边的位移动到首字节的最高位上。这个过程一直持续下去直到所有的位都轮转到位。
bit_rot_left 的时间复杂度为O(nβ),其中n为要向左轮转的位的个数,β是缓冲区中位的个数。这是因为,对于每次轮转,要进行(β/8)+1次移动。
位操作的实现代码:
/* bit.c */
#include
#include “bit.h”
/* bit_get */
int bit_get(const unsigned char *bits, int pos)
{
unsigned char mask;
int i;
/* Set a mask for the bit to get. */
mask = 0x80;
for (i = 0; i < (pos % 8); i++)
mask = mask >> 1;
/* Get the bit. */
return (((mask & bits[(int)(pos / 8)]) == mask) ? 1 : 0);
}
/* bit_set */
void bit_set(unsigned char *bits, int pos, int state)
{
unsigned char mask;
int i;
/* Set a mask for the bit to set. */
mask = 0x80;
for (1 = 0; i < (pos % 8); i++)
mask = mask >> 1;
/* Set the bit. */
if (state)
bits[pos / 8] = bits[pos / 8] | mask;
else
bits[pos / 8] = bits[pos / B] & (~mask);
return;
}
/* bit_xor */
void *bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx, int size)
{
int i;
/* Compute the bitwise XOR (exclusive OR) of the two buffers. */
for (i = 0; i < size; i++)
{
if (bit_ get(bits1, i) != bit_ get(bits2, i))
bit_set(bitsx, i, 1);
else
bit_set(bitsx, i, 0);
}
return;
}
/* bit_rot_left */
void bit_rot_left(unsigned char *bits, int size, int count)
{
int fbit,
lbit,
i,
j;
/* Rotate the buffer to the left the specified number of bits. */
if (size > 0)
{
for (j = 0; j < count; j++)
{
for (i = 0; i <= ((size - l) / 8); i十十)
{
/* Get the bit about to be shifted off the current byte. */
lbit = bit_get(&bits[i], 0);
if (i == 0)
{
/* Save the bit shifted off the first byte for later. */
fbit = lbit;
}
else
{
/* Set the rightmost bit of the previous byte to the leftmost *
* bit about to be shifted off the current byte. */
bit_set(&bits[i - 1], 7, lbit);
}
/* Shift the current byte to the left. */
bits[i] = bits[i] << 1;
}
/* Set the rightmost bit of the buffer to the bit shifted off the *
* first byte. */
bit_set(bits, size - 1, fbit);
}
}
return;
}