首先需要了解整数二进制的三种表示形式:原码、反码和补码。
原码就是一个整数二进制的表示方式,对于正整数来说原码、反码、补码都相同。
以-5为例:
int类型占4个字节,32个bit,最高位为符号位,1为负,0为正。
-5原码:1000 0000 0000 0000 0000 0000 0000 0101
-5反码:1111 1111 1111 1111 1111 1111 1111 1010 (符号位不变,其他1变0,0变1)
-5补码:1111 1111 1111 1111 1111 1111 1111 1011 (反码+1,得到的就是补码)
整数在内存中存储的是补码!!!!
用VS验证一下,vs编译器在内存窗口时以十六进制展示的
fb ff ff ff 转换为二进制 1111 1011 1111 1111 1111 1111 1111 1111
二、移位操作符<<:左移。整数在内存中存储的二进制位向左移,空位补0。
例如:
int a = -5; int b = a << 2;
b的补码:1111 1111 1111 1111 1111 1111 1110 1100
b的反码:1111 1111 1111 1111 1111 1111 1110 1011 (补码-1)
b的原码:1000 0000 0000 0000 0000 0000 0001 0100
所以b等于-20。
>>:右移。右移分为逻辑右移和算术右移,整数在内存中存储的二进制位向右移。
算术右移规则:右边丢弃,左边补原来的符号位。
逻辑右移规则:右边丢弃,左边补0。
逻辑右移还是算术右移取决于编译器,一般常见的编译器是算术右移。
例如:
int a = -5; int b = a >> 2;
在vs编译器中:
b的补码:1111 1111 1111 1111 1111 1111 1111 1110
b的反码:1111 1111 1111 1111 1111 1111 1111 1101
b的原码:1000 0000 0000 0000 0000 0000 0000 0010
所以b等于-2。
三、位操作符&:按位与 |:按位或 ^:按位异或
直接用例子来讲解:
&:
int a = 3; int b = -2; int c = a & b;
a在计算机中存储的二进制:0000 0000 0000 0000 0000 0000 0000 0011
b在计算机中存储的二进制:1111 1111 1111 1111 1111 1111 1111 1110
a & b (都为1取1,其余都是0): 0000 0000 0000 0000 0000 0000 0000 0010
c的补码:0000 0000 0000 0000 0000 0000 0000 0010
c的最高位是0,所以c是正数,因此c的补码等于原码。
所以c等于2。
|:
int a = 3; int b = -2; int c = a | b;
a在计算机中存储的二进制:0000 0000 0000 0000 0000 0000 0000 0011
b在计算机中存储的二进制:1111 1111 1111 1111 1111 1111 1111 1110
a | b (有1得1): 1111 1111 1111 1111 1111 1111 1111 1111
c的补码:1111 1111 1111 1111 1111 1111 1111 1111
c的反码:1111 1111 1111 1111 1111 1111 1111 1110
c的原码:1000 0000 0000 0000 0000 0000 0000 0001
所以c等于-1。
^:
int a = 3; int b = -2; int c = a | b;
a在计算机中存储的二进制:0000 0000 0000 0000 0000 0000 0000 0011
b在计算机中存储的二进制:1111 1111 1111 1111 1111 1111 1111 1110
a ^ b (相同为0,相异为1): 1111 1111 1111 1111 1111 1111 1111 1101
c的补码:1111 1111 1111 1111 1111 1111 1111 1101
c的反码:1111 1111 1111 1111 1111 1111 1111 1100
c的原码:1000 0000 0000 0000 0000 0000 0000 0011
所以c等于-3。
位操作符的应用:
通过上述的讲解,我们可以知道 a^a = 0。
因此这道题我们可以这样解:
int a = 10; int b = -5; a = a ^ b; b = a ^ b;//a ^ b ^ b = a a = a ^ b;// a ^ b ^ a = b
四、取反操作符
~:取反操作符。将计算机中存储的二进制数按位取反。
实际应用:
将 0000 0000 0000 0000 0000 0000 00001010
变成 0000 0000 0000 0000 0000 0000 0000 1110
我们可以用
0000 0000 0000 0000 0000 0000 00001010
| 0000 0000 0000 0000 0000 0000 0000 0100(1的二进制左移两位)
那如何将 0000 0000 0000 0000 0000 0000 0000 1110
变成 0000 0000 0000 0000 0000 0000 00001010呢?
可以用
0000 0000 0000 0000 0000 0000 0000 1110
&1111 1111 1111 1111 1111 1111 1111 1011(~0000 0000 0000 0000 0000 0000 0000 0100)
五、逻辑操作符&&:逻辑与 ||:逻辑或
这两个操作符想必大家都十分熟悉,那下面这段代码会输出什么呢?
#includeint main() { int i = 0, a = 0, b = 2, c = 3, d = 4; i = a++ && ++b && d++; printf(" a = %dn b = %dn c = %dn d= %dn", a, b, c, d); return 0; }
答案是
当&&的左操作数为假的时候就不再往后计算了,同样当||的左操作数为真的时候也不再往后计算了。
六、逗号表达式,:逗号表达式。从左往右依次执行,整个表达式的结果是最后一个表达式的结果。
例如:
int a = 3; int b = 5; int c = 6; int d = (a += 2, b = a - c, c = a + 2 * b);
执行完这些语句后,a = 5 ,b = -1 ,c = 3,d = 3。
七、sizeof大家都知道sizeof是用来求取操作数在内存中的大小,但是sizeof括号内的表达式不参与运算你知道吗?
#includeint main() { int a = 3; int b = 5; short c = 6; printf("%dn", sizeof(c = a + b)); printf("%dn", c); return 0; }
这段代码的运行结果是
可以发现c并不等于8,因此sizeof括号内的表达式是不参与运算的。



