通常位操作以较小的数据宽度完成,例如int,unsigned int或wchar_t。假设我们想要以更长的格式使用位串,如何在char字符串中移位,获取和设置位的位?
一种方法可能是使用传统方法进行分割和征服,但我们如何确保比特结转?
给出
#define numberOfState 2000 // number of bits
#define numberOfBitsIn1Byte 8
char* record;
int numberOfCharRequiredToRepresentBits =
ceil(((float)numberOfState/(float)numberOfBitsIn1Byte));
record = (char*) malloc(sizeof(char)*numberOfCharRequiredToRepresentBits);
// record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
// optional : initialization by doing the set bit according to
// input from files. After which, do free(record);
我们如何进行比特操作,例如
i. shift the *record
ii. get bits from a specific bit position in *record
iii. set bits from a specific bit position in *record
答案 0 :(得分:1)
您的比特流本质上是一个char数组。因此,要执行这些操作,您需要处理这些char元素。
我。移位操作取决于您想要移位的位数。 如果数字是8的倍数,则非常简单,只需将左边的元素复制为字节数,因为数字是8的倍数。 如果数字小于8,则对数组的每个元素执行操作,但是您需要或前一个元素的溢出位。例如,在左移,元素i必须包含元素i + 1的溢出位,并且在右移,元素i-1的溢出位。 您想要移位的任何其他位数都可以通过这两个操作的组合来实现。例如,左移18,是16的移位,然后是2的移位。 在任何情况下,您都需要注意开始位串的哪一侧,这样就不会丢失数据。
II。为了获得比特流的第n位,可以访问索引为n / 8(整数除法)的元素,并从中获取n%8位。
III。与ii。几乎相同。
答案 1 :(得分:1)
请尝试使用以下代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isLittleEndian = 1;
void checkEndian(void)
{
union
{
short inum;
char c[sizeof(short)];
} un;
un.inum=0x0102;
if(un.c[0]==1 && un.c[1]==2)
{
printf("big_endian.\n");
isLittleEndian = 0;
}
else if(un.c[0]==2 && un.c[1]==1)
{
printf("little_endian.\n");
isLittleEndian = 1;
}
}
void shift_L(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst, src + shiftBytes, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = 0; i < len; i++)
{
if (isLittleEndian)
{
tmp = *(dst+i) << 8 | *(dst+i+1);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp + 1);
}
else
{
tmp = *(short *)(dst+i);
tmp <<= shiftBits;
*(dst+i) = *((char *)&tmp);
}
}
}
}
void shift_R(char *src, char * dst, int len, int n)
{
int shiftBytes = n/8;
int shiftBits = n%8;
memset(dst, 0, len);
memcpy(dst + shiftBytes, src, len - shiftBytes);
if (shiftBits)
{
int i = 0;
unsigned short tmp = 0;
for ( i = len -1; i >= 0; i--)
{
if (isLittleEndian)
{
tmp = *(dst+i-1) << 8 | *(dst+i);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp);
}
else
{
tmp = *(short *)(dst+i-1);
tmp >>= shiftBits;
*(dst+i) = *((char *)&tmp+1);
}
}
}
}
int getBit(char *src, int n)
{
unsigned char tmp = *(src + n/8);
unsigned char mask = (0x1 << (8 - n%8 - 1));
int bit = 0;
bit = (tmp & mask) > 0;
printf("%d", bit);
}
void setBit(char *src, int n, int bit)
{
unsigned char * pTmp = src + n/8;
unsigned char mask = (0x1 << (8 - n%8 - 1));
if (bit)
{
*pTmp |= mask;
}
else
{
*pTmp &= ~mask;
}
}
void dumpBin(unsigned char *src, int len)
{
int i = 0;
int j = 0;
unsigned char mask = 0;
for ( i = 0; i < len; i++)
{
for ( j = 0; j < 8; j++)
{
mask = 0x1 << 8 - j - 1;
printf("%d",(*(src + i) & mask) > 0);
}
}
}
void main()
{
char *record = "NAXHDKAN552ajdasdadNDfadsEBEAfA8gda5214S";
//char *record = "NAXHDKA";
int recordLen = strlen(record);
char * buffer = NULL;
int i = 0;
checkEndian();
recordLen = recordLen + recordLen%2;
buffer = malloc(recordLen);
memcpy(buffer, record, recordLen);
printf("\n input bit stream:\n");
dumpBin(buffer, recordLen);
printf("\n bit stream from getBit:\n");
for ( i = 0; i < recordLen*8; i++)
{
getBit(buffer, i);
}
setBit(buffer, 8, 1);
setBit(buffer, 9, 0);
setBit(buffer, 10, 1);
setBit(buffer, 11, 1);
printf("\n bit stream after setBit:\n");
dumpBin(buffer, recordLen);
shift_L(record, buffer, recordLen, 1);
printf("\n bit stream after shift_L:\n");
dumpBin(buffer, recordLen);
shift_R(record, buffer, recordLen, 9);
printf("\n bit stream after shift_R:\n");
dumpBin(buffer, recordLen);
printf("\n");
free(buffer);
}