注册 | 登录 忘记密码? 51cto首页 | 博客 | 论坛 | 招聘
热点文章 CCNA教材推荐
 帮助

C:位运算


2007-11-29 14:00:34
 标签:C   [推送到技术圈]

版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。
1.负数表示-二类补数(twos complement)
    一般使用二类补数表示负数,最左边一位为符号位.
    将一个十进制负数转化为二进制符号数时,首先给这个数加1,然后取绝对值,再将其转换为二进制,最后对这个二进制求补.
    [1]-5
    [2]-4
    [3]4
    [4]0000 0100
    [5]1111 1011
    将一个负数从二进制转换为十进制,首先对其所有位求补,然后将结果转换为十进制,再改变其符号,最后再减1.
    [1]1111 1011
    [2]0000 0100
    [3]4
    [4]-4
    [5]-5
    使用二类补数表示数字时,用n位可存储的最大正数是2n-1-1,用n位可存储的最小负数-2n-1.
    假设整数占32位(4字节),此时可存储的最大正数231-1,最小负数-231,而如果是无符号整数,即unsigned int,其表示范围为0至232-1.

2.按位与和按位或
    按位与经常用于屏蔽一个数中的某些位,
   word&=0x1//除最右边4位外,其余位清零
    按位或经常用于将某些位设定为1
   word|=0x1//将最右边4位设定为1

3.异或运算
    异或运算可以交换两个值而不需要使用临时变量.
/*exchange two integer values*/
void swap(int *a,int *b)
{
    *a^=*b;
    *b^=*a;
    *a^=*b;
}
    如果某数与1进行异或运算,可以达到取反的效果,0^1=1,1^1=0.
    这里假设机器的整型数长度为32位,对整数0的31位取反,得到最大整数.
int main()
{
   
int a=0;
    printf(
"%i,%i",a,a^0x7fffffff);
   
return 0;
}

4.几个经典的位运算函数
4.1求当前机器无符号整型最大长度
/*the max length of unsigned int*/
int  int_size ()
{
    unsigned
int  bits;
   
int size = 0;

    bits = ~0;

    
while ( bits ) {
       ++size;
       bits >>= 1;
    }
   
return size;
}

4.2移位运算
/*a bit mover for unsigned int
  if n > 0 move left for n bits,else move right*/

unsigned
int bit_shift (unsigned int value,int n)
{
   
int intsize=int_size();     /*the length of unsigned int*/

    
if(n>0 && n< intsize)       /*move left*/
      value<<=n;
   
else if (n<0 && n> -intsize)  /*move right*/
      value>>=-n;
   
else
      value=0;
   
return value;
}

4.3循环移位运算
/*a bit rotate mover for unsigned int
  if n > 0 move left for n bits,else move right*/

unsigned
int bit_rotate (unsigned int value, int n)
{
    unsigned
int result,bits,intsize;

    intsize=int_size();  
/*the length of unsigned int*/

    
if(n > 0)
      n=n % intsize;
   
else
      n=-(-n % intsize);

    
if(n==0)
      result=value;
   
else if(n >0 ){               /*move left*/
        bits=value >> (intsize-n);
/*bits should be in the rightest*/
        result=value << n|bits;
    }
else{                      /*move right*/
        n=-n;
        bits=value << (intsize-n);
/*bits should be in the leftest*/
        result=value >> n|bits;
    }
   
return result;
}

4.4返回无符号整型数value中从右起第p位的值
/* get bit No.p(from right) of value to see if it is on */
int  bit_get (unsigned int  value, int  n)
{
   
int intsize=int_size();       /*the length of unsigned int*/

    
if ( p < 0  || p > intsize-1 )/*out of range*/
      
return  0;

    
if ( (value >> p) & 1 )
      
return 1;
   
else
      
return 0;
}

4.5将无符号整型数value中从右起的第p位置1
/* set bit No.p(from right) of value on */
unsigned
int  bit_set (unsigned int value, int  p)
{
   
int intsize=int_size();       /*the length of unsigned int*/

    
if ( p < 0  || p > intsize-1 )/*out of range*/
      
return  0;

    
return  value | (1 << p);
}

4.6返回无符号整型数value中从第p位(右起)向右n位的值
[1]~(~0 << n)表示最右边n位全为1;
[2]value >> (p+1-n)表示将目标位字段移至最右端;
/*get n bits of value at position p(from right) */
unsigned bits_get (unsigned
int value, int p, int n)
{
    
int intsize=int_size();  /*the length of unsigned int*/

    
if ( n < 0  || p < 0  ||  p + n > intsize )
      
return  0;
   
return(value >> (p+1-n)) & ~(~0 << n);
}

4.7将无符号整型数value中从第p位(右起)向右n位设置为y最右边n位的值
[1]~(~0 << n)表示最右边n位全为1;
[2](~(~0 << n) << (p+1-n)表示将这n个1位左移至位置p;
[3]~(~(~0 << n) << (p+1-n))表示将从位置p开始的n位设置零,其余位设置一;
[4]unsigned tar=bits_get(y,n-1,n);取出y的低n位;
/*set n bits of value at position p(from right) with bits of y*/
unsigned bits_set (unsigned value,
int p, int n, unsigned int y)
{
   
int intsize=int_size();  /*the length of unsigned int*/

    
if ( n < 0  ||  p < 0  ||  p + n > intsize )
      
return  0;
    unsigned tar=bits_get(y,n-1,n);
   
return (value & ~(~(~0 << n) << (p+1-n))) | tar;
}

本文出自 “子 孑” 博客,转载请与作者联系!





    文章评论
 
2007-11-29 16:26:15
写的很详细 很好 可以学到许多C/C++比较基础的东西 很有用

2007-11-30 16:34:19
我是刚开始学C
我想问下你文中指出的库函数,是静态函数库.a ?
不需要使用 -lm 或-L 参数来指定?

2007-11-30 17:18:26
[1]“我想问下你文中指出的库函数,是静态函数库.a ?”-〉这句话有问题吧。.a是linux下的库文件,win下面是.lib。这个和静态动态没关系。
[2]一般的编译器默认设置是连接动态库,这就要求在程序执行的时候需要的动态库必须存在。改变编译选项可以变为静态连接,这样生成的程序运行时不需要库的支持,但是文件的尺寸一般较大。
[3]“不需要使用 -lm 或-L 参数来指定”-〉我用的是IDE环境,所以不是"手写"make文件,IDE自己会生成的。

2007-11-30 19:21:30
哦,明白了。谢谢啊
因为我是学习LINUX 的C编程,对于库文件的理解不是很清楚。加上一些概念比较多,看了文章才问起的。
现在想明白了。
IDE环境还不错啊,可以自动生成。。
指定库--文件的尺寸一般较大--建议指定呢?还是一般都不指定?
我在WIN下用的VB LINUX下用的VI 编

2007-11-30 22:44:54
"指定库--文件的尺寸一般较大--建议指定呢?还是一般都不指定?"->我觉得这个需要看你特定的目的啦。

2007-12-26 11:48:21
你 很 棒 啊 ,呵 呵 !

 

发表评论

昵   称:
验证码:  点击图片可刷新验证码  博客过2级,无需填写验证码
内   容: