/* * 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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-09 20:59:29