您的位置:首页 > 编程语言 > C语言/C++

C语言学习笔记:16_位运算

2015-07-06 14:04 591 查看
/*
* 16_位运算.c
*
*  Created on: 2015年7月6日
*      Author: zhong
*/
#include <stdio.h>
#include <stdlib.h>

/* 位运算:
* 所谓的位运算是指以二进制位为对象的运算。
* c语言中位运算符有:
*  & 按位与
*  | 按位或
*  ^ 按位异或
*  ~ 按位取反
*  << 左移
*  >> 右移
*
*	除了 ~ 按位取反运算符以外,均为二目运算符。 两边的运算对象只能是整型或者字符 型数据
*----------------------------------------------------------------------------------------
* 一:& 按位与 : 两个相应的二进制位都为1,则这位的结果值为1,否则为0; 0&0=0, 0&1=0; 1&0=0, 1&1=1
*	例:
*		00000111 (7)
*	&	00000101 (5)
*	——————————————————
*		00000101 (5)
*	因此:7&5=5。如果参加&运算的是负数,则以袚形式表示 为二进制数,然后按位进行‘与’操作
*	注意: &&与&的区别, &&是逻辑与运算符,7&&5值为1,因为非0数为真,真真得真=1;
*
*	按位与‘&’的用途:
*	 1:将一个数‘清零’
*		只要找一个二进制数,原来的数中为1的位,新数中相应的位为0进行&运算,即可达到清零目的。
*		任何数与0 按位与操作,者为0; 因为两个二进制位,只要有一个是0,其为0;
*	 2:取一个数中某些指定位:
*	 		如:  取300四个字节中的最低一个字节
*	 		00000000 00000000 00000001 00101100 (300)
*	 		00000000 00000000 00000000 11111111 (255)
*	 		————————————————————————————————————————————————————————
*			00000000 00000000 00000000 00101100  (44)
*------------------------------------------------------------------------------------------
* 二:| 按位或 : 两个相应的二进制位只要一个为1,则这位的结果值为1;只有两个为0时,才为0; 0&0=0, 0&1=1; 1&0=1, 1&1=1
*		00000111 (7)
*	|	00000101 (5)
*	——————————————————
*		00000111 (7)
*--------------------------------------------------------------------------------------------
* 三: '^' 异或运算符: 参加运算的两个 二进制位异号,则两位相同时为假(0),不同是为真(1)  即  0^0=0; 0^1=1, 1^0=1, 1^1=0
*		  异或的意思是判断两个相应 的位值是否0 ‘异’,为‘异’就取真(1),否则为假(0)
*		00000111 (7)
*	^	00000101 (5)
*	——————————————————
*		00000010 (2)
*	应用 :
* 1、将二进制各位'取反'
*		00111010
*	^	11111111
*	————————————————
*	    11000101
* 2、与0相^,保留原直
*
* 3、交换两个值,不用临时变量
*   a=a^b; b=b^a; a=a^b; 这样就可以交换两个变量的值了
*		a=7,b=5;
*		00000111 (7)
*	^	00000101 (5)
*	——————————————————
*		00000010 (2)  a=a^b=2
*	^	00000101 (5)
*	——————————————————
*		00000111 (7)  b=a^b=7;(和b=b^a意思一样的)
*	^	00000010 (2)
*  ——————————————————
*  	00000101 (5)  a=b^a=5;(和a=a^b意思是一样的)
* 4、一个数和自己异或,结果为0
* 5、两个数异或顺序可以互换的,结果一样。 如9^5^9= 9^9^5 =0^5 =5;
*
*----------------------------------------------------------------------------------------
* 四:~ 是一个单目运算符,用来对一个二进制数按位取反,即0变1,1变0
* 	~	00000111 (7)
* 	——————————————————
* 		11111000 (248)  ~7=248
*
*----------------------------------------------------------------------------------------
* 五:左移运算:<< 用来将一个数的各二进制位全部左移若干位,高位左移溢出时,舍去。右边补0
* 例如  a=15  将a左移2位 a=a<<2  =60;
*
*   <<2    00 00 11 11  (15)
* 	———————————————————————
*     (00) 00 11 11(00) (60)
*     溢出舍去                        右补0
*
*   左移运算的特点: 一个数左移1位相当于这个数乘以2,左移2位相当于这个数乘以2^2=4。(前提条件是,高位溢出的位不能是1,只能是0)
*   			左移比乘法运算快,所以编译程序自动将乘2的运算左移一位为实现,将乘以2^n为左移n位。
*
*	面试题:用最有效率的方法算出2乘以8等於几
*			2<<3; 相当于2*2^3=2*8
*
*----------------------------------------------------------------------------------------
* 六:右移运算 >>表示将二进制位右移n位,移到右端的低位被舍弃,对无符号数,高位补0。
*   例如:a=017; a=a>>2;
*  >>2 	00 00 11 11                (17)
*  ———————————————————
*  	  (00) 00 00 11 (11) (3)
*  	      左补0           此2位舍弃
*	右移运算的特点: 和左移刚好相反啦。一个数右移1位相当于这个数除以2,右移n位相当于除以2^n次方法。
*	在右移时,要注意符号位的问题。对无符号数,右移左边高位补0;对于有符号数据,如果原来符号位为0(正数),则左边补0。
*						如果符号位原来为1(负数) ,则左移补0还是1,要取决于所用的计算机系统。有的补0,有的补1。
*							补0的称为"逻辑右移"不考虑符号问题。补1的称为"算术右移"保持原来符号
*----------------------------------------------------------------------------------------
*七:位运算赋值运算符:即位运算与赋值运算符组合 :&= ;|= ;>>= ;<<=  ;^=
*
*	作用和 *= ,+=是一样的。 比如 a&=b,相当于a=a&b;
*
*
*若两个不同长度的数据进行位运算,系统会将二者按右端对齐,右侧补0;
*
*----------------------------------------------------------------------------------------
*/
//位运算 & ‘与’
void bit_arith_and() {
int a = 7, b = 5;
printf("7&5=%d\n", a & b); //output:5
a = 300, b = 255;
printf("300&255=%d\n", a & b); //output:44
}
//位运算 | ‘或’
void bit_arith_or() {
int a = 7, b = 5;
printf("7|5=%d\n", a | b); //output:7
a = 300, b = 255;
printf("300|255=%d\n", a | b); //output:511
}
//位运算 ^ ‘异或’
void bit_arith_and_or() {
int a = 7, b = 5;
printf("7^5=%d\n", a ^ b); //output:2
}
//4:使用^(异或)算法,交换两个变量的值
void use_or_swap_number() {
int a = 10, b = 11;
a = a ^ b; //1
b = b ^ a; //11-1=10
//	b=a^b; //和上面哪句一样的
a = a ^ b; // 1+10=11
printf("使用^(异或)算法交换两个数:a=%d,b=%d\n", a, b);
}
//左移
void left_shift() {
printf("%d", 2 << 2); //2*2^2=8
}
//右移
void right_shift() {
printf("%d", 8 >> 2); //8/2^2=2;
}

//用按位与&判断一个数是奇数还是偶数
void exercise_1() {
/**
*奇数与偶数的特征:
* 1111 (15)
* 1001 (9)
*
* 1110 (14)
* 1010 (10)
*
* 根据上面可发现:右数的最后一位都是1,偶数最后一位都是0;
* 解题思路: 只要用这个数&1 就可以取出 最后一位,如果是1,就是奇数。是0就是偶数
* 1111
* 0001 (&1)
* ————
* 0001 这样就取出了最后一位
*
*/

int a = 15;
int b = 20;
a & 1 == 1 ? printf("%d是奇数\n", a) : printf("%d是偶数\n", a); //使用三目运算符
b & 1 == 1 ? printf("%d是奇数\n", b) : printf("%d是偶数\n", b); //使用三目运算符

}

//用位运算输出一个十进制数的二进制形式
void printf_bin(int number) {
//	int count = sizeof(number)*8-1; //获得这个数的位数
int count = (sizeof(number)<<3)-1; //获得这个数的位数  左移n位相当于*2的n次方。   <<3==*8; 由于算术运算符优先级高于位运算符,所以 要加()

while (count >= 0) {
int n_ = number >> count & 1; //第一次左移31位&1取得这一位数。。。。。。
printf("%d", n_);
if (count % 4 == 0) { //四位空一格:0000 0000 0000 0000 0000 0000 0000 1111
printf(" ");
}
count--;
}
printf("\n");
}

int main() {
//	bit_arith_and();
//	bit_arith_or();
//	bit_arith_and_or();
//	use_or_swap_number();
//	left_shift();
//	right_shift();
//	exercise_1();
printf_bin(15); //output:0000 0000 0000 0000 0000 0000 0000 1111

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: