文章目录
- 一、操作符
- 1. 操作符的分类
- 2. 操作符的属性
- 2.1 优先级
- 2.2 结合性
- 二、二进制
- 1. 原码、反码、补码
- 2. 位操作符
- 2.1 左移操作符 <<
- 2.2 右移操作符 >>
- 2.3 & | ^ ~
一、操作符
在C语言中,操作符是用于执行各种操作的符号,它们是构成语法、表达式的基本元素
1. 操作符的分类
我们可以把操作符分为以下几类:
我们在以前已经知道了部分操作符并运用了,对于其他操作符,慢慢了解~
2. 操作符的属性
C语言的操作符有两个重要的属性:优先级、结合性
2.1 优先级
如果一个表达式包含多个运算符,不同运算符计算的优先级是不一样的。比如乘除运算符的优先级就比加减运算符的优先级高。
2.2 结合性
如果两个运算符优先级相同,优先级没办法确定先计算哪个,这时候就看结合性了,根据运算符是左结合,还是右结合,决定执行顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符 = 就是右结合。
优先级和结合性可以参考下表:链接
二、二进制
我们首先应该知道的是:
-
数据在内存中都是以二进制的形式存储的,二进制中满2进1,它的每一位都由0或1组成。
-
十进制数转换为二进制的方法是:用这个数除以2,得到的余数就是0或1;除2后的数再除2,得到的余数是0或1……如法炮制除完,将得到的0和1的序列自后向前从左到右排列,就是这个整数的二进制。举个栗子:将125转换为二进制
这样算完后,把右侧的余数自上而下从左到右排开,就是125的二进制了:1111101 -
二进制转换为十进制:二进制从左至右的每一位依次乘以2的0次,2的1次,2的2次……加和,得到这个整数的十进制。举个例子,将1111101转换为十进制,即(1×1)+(0×2)+(1×4)+(1×8)+(1×16)+(1×32)+(1×64),等于125
-
每类整型数据所占空间都不一样,比如short类型占据两个字节——16个bit的大小,而我们下面主要使用的 int 类型,占据4个字节——32个bit的大小。也就是说,int类型的数据的二进制原码、反码、补码,都是由32个0或1组成的,将十进制数翻译为二进制后,前面的空位都用0(符号位是0或1)补全。
1. 原码、反码、补码
整数的二进制有三种表示方法:原码、反码、补码。
有符号整数的三种表示方法里,都分为符号位和数值位两部分。二进制序列中,最高位是符号位,剩下的都是数值位。
在符号位上,0表示正,1表示负
要注意的是:
- 正整数(包括0)的原码、反码、补码完全相同
- 负整数的原码、反码、补码都不相同
那么这三种表示方法具体是什么呢?
- 原码:直接将数值按照正负数的形式转换为二进制,得到的序列
- 反码:(对于负数来说)原码的符号位不变,剩下每一位取反,得到的序列
- 补码:(对于负数来说)反码+1,得到的序列
tip:(对于负数来说)补码的符号位不变,数值位每一位取反,再+1,就能得到原码
举例:
十进制数10
原码是00000000 00000000 00000000 00001010
反码是00000000 00000000 00000000 00001010
补码是00000000 00000000 00000000 00001010
十进制数-10
原码是10000000 00000000 00000000 00001010
反码是11111111 11111111 11111111 11110101
补码是11111111 11111111 11111111 11110110
对于所有整形数据来说:内存中存放的都是他们的补码
原因了解一下就可以,看不懂也冇关系啦:使用补码,可以将符号位和数值位统一处理,同时加法和减法也可以统一处理(CPU只有加法器)。此外,补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
2. 位操作符
位操作符是一类针对二进制的操作符,位操作符的操作数只能是整数
2.1 左移操作符 <<
<< 的作用,是让补码的每一位数左移几位,原本最左面的几位数丢弃,最右边空缺出的位置用0补满。
比如,来个int n = 10
,那么n的补码就是00000000 00000000 00000000 00001010
如果执行语句int m = n<<2
,就是n的补码的每一位向左移动2位,左边2位抛弃,右边2位补0,即00000000 00000000 00000000 00101000,转换为原码还是这个,即 m=40,n不变。
2.2 右移操作符 >>
右移操作符的移位方式分为两种:
- 逻辑右移:右边的几位丢弃,左边空缺的几位用0填充
- 算术右移:右边的几位丢弃,左边空缺的几位用原值的符号位数填充
在实际使用中,用哪一种移位方式其实是取决于编译器的,但常见的编译器都是默认执行算术右移的,下面我们也使用这一种方法。
比如int n = -10
,那么n的补码就是11111111 11111111 11111111 11110110。如果执行语句int m = n>>2
,就是n的补码每一位向右移动2位,右边2位丢弃,左边2位用1填充,即11111111 11111111 11111111 11111101,转换为原码是10000000 00000000 00000000 00000011,即m= -3,n不变。
WRANING:不要在<<或>>后加负数,这样是无定义的!
2.3 & | ^ ~
这几个位操作符分别是
&:按位与
| :按位或
^:按位异或
~:按位取反
让我们分别来说……
-
&:n & m,计算方式是,把两个数n和m的补码对齐,同一位上的两个数中只要存在0,计算结果的这一位就是0。两个数都是1,这一位就是1;
-
| :n | m,计算方式是,把两个数n和m的补码对齐,同一位上的两个数中只要存在1,计算结果的这一位就是1。两个数都是0,这一位就是0;
-
^:n ^ m,计算方式是,把两个数n和m的补码对齐,同一位上的两个数相同,计算结果的这一位就是0。两个数不同,这一位就是1。 ^ 有几个公式:
-
~: ~n,计算方式是,把数n的补码的每一位都取反。
注意:这些计算都是对补码的计算,得到的也是结果的补码,换算成原码才是真正的结果!
说了这么多,这些操作符具体有啥用呢?敬请期待《二进制·之其二》~
本篇完,感谢阅读