位操作
在压缩和解压数据时,常常需要在小于一个字节的数量级上 进行数据操作。因此,在讨论各种数据压缩方法之前,首先必须熟悉一些对数据位进行的操作。这些操作非常重要,因为C语言本身只有一小步等内在的、不可分割的操作数。下面是介绍一些位操作的基础,和参阅博客:位操作基础篇之位操作全面总结
下面是自己对博客内容简单的总结。
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <stdbool.h>
/*位运算小技巧*/
/*1、判断奇偶*/
#define IS_EVEN(n) {printf("number %d is:",(n));\
(n) & 1 == 1?printf("奇数\n"):printf("偶数\n");}
/*2、数据交换*/
#define SWAP(a,b) { if (*a != *b){ \
*a ^= *b;\
*b ^= *a;\
*a ^= *b;\
}\
}
/*3、交换符号,就是将整数变为负数,负数变为整数*/
#define SIGN_REVERSAL(n) (~(a) + 1)
/*4、求绝对值*/
#define ABS(n) ((n) >> 31 == 0?(n):(~(n) + 1))
/*5、0到100中刷选素数方法*/
#define MAXN 100
bool flag[MAXN];
int primes[MAXN/3 + 1],pi = 0;
void getPrime_1()
{
int i,j;
memset(flag,false,sizeof(flag));
for(i = 2;i < MAXN; i++){
if(!flag[i]){
primes[pi++] = i;
for(j = i; j < MAXN; j += i){
flag[j] = true;
}
}
}
}
void PrintfArray()
{
int i = 0;
for(; i < pi; i++)
printf("%d ",primes[i]);
puts("");
}
/*位压缩筛选素数
*其方法和上面的一样,只是在flag中用位来对应素数的位置
*
* */
int flag_2[MAXN/32];
void getPrime_2()
{
int i,j;
pi = 0;
memset(flag_2,false,sizeof(flag_2));
for(i = 2;i < MAXN; i++){
if(!((flag_2[i/32] >> (i%32)) & 1)){
primes[pi++] = i;
for(j = i; j < MAXN; j += i){
flag_2[j/32] |= (1<<(j%32));
}
}
}
}
int main()
{
IS_EVEN(20);
int a = 10,b=20;
printf("交换前:a = %d,b = %d\n",a,b);
SWAP(&a,&b);
printf("交换后:a = %d,b = %d\n",a,b);
printf("a = %d,SIGN_REVERSAL(a) = %d\n",a,SIGN_REVERSAL(a));
printf("ABS(a) = %d\n",ABS(a));
puts("用筛素数法求100以内的素数");
getPrime_1();
PrintfArray();
puts("用位运算筛素数法求100以内的素数");
getPrime_2();
PrintfArray();
return 0;
}
下面是数据压缩和解压中经常 遇到的位操作函数介绍
/*bit.c*/
#include <string.h>
#include <stdio.h>
/****************************************************************
*获取bis中处于位置pos的位的状态。
*返回值:相应位的状态:1or0。
***************************************************************/
int bit_get(const unsigned char * bits, int pos)
{
unsigned char mask;
int i;
/*设置掩码*/
mask = 0x80;
for (i = 0; i < (pos % 8); i ++)
mask = mask >> 1;
/*获得当前位的数值*/
return (((mask & bits[(int)(pos / 8)]) == mask )? 1:0);
}
/**********************************************************
*设置bits中处于pos的位的状态(根据state的数值来设置)。
*最左边位置位0,状态值必须为0或1;
*无返回值
* ******************************************************/
void bit_set(unsigned char * bits, int pos, int state)
{
unsigned mask;
int i;
mask = 0x80;
for (i = 0; i < (pos % 8); i ++)
mask = mask >> 1;
if (state)
bits[pos/8] |= mask;
else
bits[pos/8] &= (~mask);
return;
}
/********************************************************************
*对bist1与bist2进行异或运算,结果保存到bitsx,
*无返回值
* *****************************************************************/
void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned char *bitsx,int size)
{
int i;
for (i = 0 ; i < size; i++){
if(bit_get(bits1,1) != bit_get(bits2, 1)){
bit_set(bitsx,i,1);
} else {
bit_set(bitsx,i,0);
}
}
return;
}
/****************************************************************
*将bits进行轮转,将位值向左移count位,操作完成后,处于最左端的
*count位移动到最右端,而且其他位也相应的轮移
* 无返回值
* **************************************************************/
void bit_rot_left(unsigned char *bits,int size, int count)
{
int fbit,
lbit,
i,
j;
if (size > 0){
for ( j = 0; j < count; j++){
for(i=0;i<=((size - 1)/8);i++){
lbit = bit_get(&bits[i],0);
if (i == 0)
fbit = lbit;
else
bit_set(&bits[i - 1],7,lbit);
bits[i] = bits[i] << 1;
}
bit_set(bits,size-1,fbit);
}
}
}
int main()
{
unsigned char a ='A' ;
int i = 0;
unsigned char b[]={'Z','B','C','D'};
printf("获得‘A’的值是:");
/*打印出来应该是01000001 0x41*/
for(i=0;i<8;i++){
printf("%d",bit_get(&a,i));
}
bit_set(&a,4,1);
/*设置完的数值应该为01001001 0x49 'I'*/
printf("\n ###%s() ,%d = %c\n",__FUNCTION__,a,a);
bit_rot_left(b,9,2);
printf("%s\n",b);
}
其中对函数bit_rot_left()具体的功能有点模糊,测试几遍还是未能理解!有知道的麻烦给具体解答下!