int main(){
/* 按位与 & 只有对应的两个二进位均为1时,结果位才为1,否则为0。
10101010000
00000100000
-------------
00000000000
*/
/*
按位或 | 只要对应的两个二进位有一个为1时,结果位就为1,否则为0。
1001
0101
-----
1101
*/
/*
按位异或 ^ 当对应的二进位相异(不相同)时,结果为1,否则为0。
1.相同数值进行异或,结果肯定是0,比如9^9
2.交换 9^5^6 == 9^6^5
3.任何数值跟0进行异或,结果还是原来的数值,9^0 == 9
4.a^b^a == a^a^b == 0^b == b
1001
0101
-----
1100
*/
/*
按位取反 ~ 对整数a的各二进位进行取反,符号位也取反(0变1,1变0)
~0000 0000 0000 0000 0000 0000 0000 1001
1111 1111 1111 1111 1111 1111 1111 0110
*/
/*
左移 << 把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2的n次方由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
0000 0000 0000 0000 0000 0000 0000 0001
000 0000 0000 0000 0000 0000 0000 00010
9<<1 -> 9 * 2的1次方 == 18
9<<2 -> 9 * 2的2次方 ==36
*/
/*
右移 >>
0000 0000 0000 0000 0000 0000 0000 0010
0 0000 0000 0000 0000 0000 0000 0000 001
1000 0000 0000 0000 0000 0000 0000 0010
1 1000 0000 0000 0000 0000 0000 0000 001
8>>1 -> 8/2 == 4
8>>2 -> 8/2的2次方 == 2
8>>n -> 8/2的n次方
*/
return 0;
}
& 按位与
功能
只有对应的两个二进位均为1时,结果位才为1,否则为0。
举例: 比如9&5,其实就是1001&101=1,因此9&5=1
规律
二进制中,与1相&就保持原位,与0相&就为0
| 按位或
功能
只要对应的二个二进位有一个为1时,结果位就为1,否则为0。
举例: 比如9|5,其实就是1001|101=1101,因此9|5=13
^ 按位异或
1> 功能
当对应的二进位相异(不相同)时,结果为1,否则为0。
2> 举例: 比如9^5,其实就是1001^101=1100,因此9^5=12
3> 规律
相同整数相^的结果是0。比如5^5=0
多个整数相^的结果跟顺序无关。比如5^6^7=5^7^6
因此得出结论:a^b^a = b
~ 取反
对整数a的各二进位进行取反,符号位也取反(0变1,1变0)
<< 左移
把整数a的各二进位全部左移n位,高位丢弃,低位补0。左移n位其实就是乘以2的n次方
由于左移是丢弃最高位,0补最低位,所以符号位也会被丢弃,左移出来的结果值可能会改变正负性
>> 右移
把整数a的各二进位全部右移n位,保持符号位不变。右移n位其实就是除以2的n次方
为正数时, 符号位为0,最高位补0
为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定
三种方法交换a b的值
借助第三方变量
int a =10; int b =11;
int temp = a;
a = b;
b = temp;
第二种
int a =10; int b =11;
a = b - a;
b = b - a;
a = b + a;
第三种利用异或进行运算
int a =10; int b =11;
a = a ^ b;
b = a ^ b;
a = a ^ b;
判断奇数偶数
1>用位与&运算符判断变量的奇偶性
a&1==1// 奇数
a&1==0// 偶数
2>取余数
if (a%2) {
printf("奇数\n");
} else {
printf("偶数\n");
}
3>三目运算
3.1>
a%2==0?printf("偶数\n"):printf("奇数\n");
3.2
a%2?printf("奇数\n"):printf("偶数\n");
编写一个函数,用来输出整数在内存中的二进制形式
void printBinary(int number){
// 记录现在挪到第几位
int temp = (sizeof(number)<<3) -1;
while( temp >=0){
// 先挪位,再&1,取出对应位的值
intvalue = (number>>temp) &1;
printf("%d", value);
temp--;
// 每输出4位,就输出一个空格
if( (temp +1) %4==0) {
printf(" ");
}
}
printf("\n");
}
原码是什么?
原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码
举例说明:
int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得:
00000000 00000000 00000000 00000011
int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得:
10000000 00000000 00000000 00000011
但是原码有几个缺点,零分两种 +0 和 -0 。很奇怪是吧!还有,在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。你需要将两个值的绝对值进行比较,然后进行加减操作 ,最后符号位由绝对值大的决定。于是反码就产生了。
反码是什么 ?
正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反
举例说明:
int类型的 3 的反码是
00000000 00000000 00000000 00000011
和原码一样没什么可说的
int类型的 -3 的反码是
11111111 11111111 11111111 11111100
除开符号位 所有位 取反
解决了加减运算的问题,但还是有正负零之分,然后就到补码了
补码是什么?
正数的补码与原码相同,负数的补码为 其原码除符号位外所有位取反(得到反码了),然后最低位加1.
还是举例说明:
int类型的 3 的补码是:
00000000 00000000 00000000 00000011
int类型的 -3 的补码是
11111111 11111111 1111111 11111101
就是其反码加1
最后总结一下:
正数的反码和补码都与原码相同。
负数的反码为对该数的原码除符号位外各位取反。
负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1
各自的优缺点:
原码最好理解了,但是加减法不够方便,还有两个零。。
反码稍微困难一些,解决了加减法的问题,但还是有有个零
补码理解困难,其他就没什么缺点了