Summary
1)C语言中支持如下4种类型的运算:
运算类型 | 运算符 |
---|---|
四则运算 | +,-,*,/,% |
关系运算 | <,>,<=,>=,==,!= |
逻辑运算 | &&,!,II |
位运算 | &,I,^,>>,<<,~ |
2)运算符的优先级:单算移比,按逻三赋。如果不同类型的运算符同时出现在一个表达式中,尽量用括号()指明运算顺序。
3)逻辑运算的短路法则:对于&&运算,第一个为假的操作数之后的其他操作数都不再计算;对于||运算,第一个为真的操作数之后的其他操作数都不再计算。因此对于if表达式的逻辑表达式,一定要考虑到后续的操作数是否需要运算到。
4)十进制负数和二进制的相互转换规则如下:
- 1)符号位:
- 2)绝对值(二进制):
- 3)按位取反:
-
4)加1:
如果一个二进制位表示的是一个负数,那么推算的方式按上述规则逐步相反。
5)在计算机中,不同数据类型的本质在于:
- a)占用的内存大小不同:如int占4字节,char占1字节
- b)表示数据的具体方式不同:如正整数用原码表示、负整数用补码表示;整数和浮点数的二进制表示方法不同。
6)位运算操作时的关键点:
- a)操作数的类型(占用的内存大小)
- b)符号位(0还是1)
- c)不同数据类型的运算要先对齐,再运算(补符号位进行对齐)
7)设置整数integer指定Bit位的值
规则如下:
- 置0:使用按位与(运算数n指定位置为0,其余为1,同integer进行&运算),如果对应位置为0,其余位置可以不变为1,这样运算数n能小一点,直观一些
- 置1:使用按位或(运算数n指定位置为1,其余为0,同interger进行|运算)
- 取反:按位异或(如一次指定多位取反)
1、四则运算
四则运算(+, -, *, /, %)
- 就是数学中的加减乘除等运算
- 遵循先乘除后加减的运算优先级
- 可以使用括号改变运算顺序
注意:
C语言中的除法运算,除数不能为0!
/和%都是除法。对于“/”,运算的结果和大类型一致。对于“%”,只能作用于整型数。
int a = 1;
int b = 2;
int c = 0;
c = a / b; // 计算得到除法的商,大类型为int,结果仍然是int
prinf(\"c = %d\\n\", c); // c = 0
c = a % b; // 计算得到出发的余数,只能作用于整型数
prinf(\"c = %d\\n\", c); // c = 1
double a = 5;
double b = 2;
double c = 3;
c = a / b; // 两个浮点数的除法,大类型为double,结果仍然是浮点数double
prinf(\"c = %f\\n\", c); // c = 2.5
c = a % n; // error,取余运算不可以作用于浮点型
2、关系运算
关系运算(<, >, <=, >=, ==, !=)
- 比较两个值大小关系或相等关系的运算
- 比较的结果为逻辑值:真(1)、假(0)
- 可以使用括号()改变关系运算的顺序
int a = 1;
int b = 2;
int c = 0;
// 对于多个运算符杂糅在一个表达式中,运算符优先级见summary 2)
c = a - b >= a + b; // 等价于:c = (a - b) >= (a + b);
prinf(\"c = %d\\n\", c); // c = 0
c = a < b + c < b; // 等价于: c = (a < (b + c)) < b;
prinf(\"c = %d\\n\", c); // c = 1
3、逻辑运算
逻辑运算(&&, ||, !)
- 逻辑运算的参与者为逻辑值(真或假)
- 任何非零值在逻辑运算中都为真
- 任何零值在逻辑运算中都为假
对于&&运算:运算数全1得1,否则为0;
对于||运算:运算数有1得1,全0为0;
对于!运算:单目运算符(只需要一个操作数),运算结果为;逻辑值;对真值取非的结果为假,对假值取非的结果为真;
- C语言中的真值对应于非零值,假值对应于零值。如:1、1.6、-1、-0.8均为真值;如0、0.0、-0等都是假值。
逻辑运算中的短路法则:
对于&&运算
- 从左向右进行,如果有一个操作数为假,则整个表达式为假
- 第一个为假的操作数之后的其他操作数不再计算
对于||运算
- 从左向右进行,如果有一个操作数为真,则整个表达式为真
- 第一个为真的操作数之后的其他操作数不再计算
4、位运算
位运算(&, |, ~, ^, <<, >>)
- 直接对数据的二进制位进行操作
- 位运算的基本单位是二进制位,所以也是一种0和1的操作
- 可以使用括号()改变位运算的运算顺序
- 位运算的操作数只能是整型数(浮点数不能进行位运算)
运算符 | 含义 | 示例 | 优先级 |
---|---|---|---|
~ | 按位求反 | ~0101 -> 1010 | 1(高) |
<< | 左移:高位移出,低位补0 | 0011 << 1 -> 0110 | 2 |
>> | 右移:低位移除,高位补符号位 | 0101 >> 2 -> 0001 | 2 |
& | 按位与 | 0111 & 1100 -> 0100 | 3 |
^ | 按位异或:相同为0,不同为1 | 0111 & 1100 -> 1011 | 4 |
I | 按位或 | 0111 & 1100 -> 1111 | 5(低) |
运算符优先级:
4.0 位运算操作时的关键点
在计算机中,不同数据类型的本质在于:
1)占用的内存大小不同:如int占4字节,char占1字节
2)表示数据的具体方式不同:如正整数用原码表示、负整数用补码表示;整数和浮点数的二进制表示方法不同。
位运算操作时的关键点
- a)操作数的类型(占用的内存大小)
- b)符号位(0还是1)
- c)不同数据类型的运算要先对齐,再运算(补符号位进行对齐)
short a = 1; // 0001
short b = 2; // 0010
int X = a - b; // a - b = -1 short;由于-1在int能表示的范围内,所以隐式转换不会出问题
// 从二进制层面来说,short类型的-1转换到int类型的-1,需要在高位补符号位,
// 即要补高16位的1,二进制值为11...11,十进制为-1
printf(\"X = %d\\n\", X); // X = -1;
X = X >> 4; // -1 >> 4,低位舍弃,高位补符号位,仍然是11...11,-1
printf(\"X = %d\\n\", X); // X = -1;
X = X * -1 * 16 >> 4; // 单 算 移 比 按 逻 三 赋
// -1*-1*16 = 16; 16 >> 4,右边移动,高位,补符号位,所以是00...0001,1
printf(\"X = %d\\n\", X); // X = 1;
// 对于一个正整数,右移n位,X >> n,相当于除以2^n;左移n位,相当于乘以2^n
// 数据符号位的具体位置由数据类型决定的,如char,最高位是第7位;int,最高位是第31位
4.1 负数的二进制表示方法
十进制负数和二进制的相互转换规则如下:
1)符号位:
2)绝对值(二进制):
3)按位取反:
4)加1:
示例如下(以1字节为例):
// 十进制数-128的二进制表示:1000 0000
1)符号位:1
2)绝对值(二进制):1000 0000
3)按位取反:0111 1111
4)加1:1000 0000 (补码)
// 另,-128,-32768等这几个负数比较特殊,在计算机中没有原码和反码,只有补码来表示,二进制位等价于-0。
// 十进制数-10的二进制表示:1111 0110
1)符号位:1
2)绝对值(二进制):0000 1010
3)按位取反:1111 0101
4)加1:1111 0110(补码)
// 如果一个二进制位表示的是一个十进制整数,通过符号位得知是个负数,则可以按相反的运算方式进行推算。
// 二进制1111 0110到十进制数的转换:-10
4)减1:1111 0101
3)按位取反:0000 1010
2)绝对值(十进制):10
1)加上符号位:-10
4.2 设置整数integer指定Bit位的值
规则如下:
- 置0:使用按位与(运算数n指定位置为0,其余为1,同integer进行&运算),如果对应位置为0,其余位置可以不变为1,这样运算数n能小一点,直观一些
- 置1:使用按位或(运算数n指定位置为1,其余为0,同interger进行|运算)
- 取反:按位异或(如一次指定多位取反)
示例如下:
// eg.1 设置整数5的第2个二进制位为1
使用按位或方式:运算数n为 0000 0010 = 2,整数5为 0000 0101
0000 0010 2
| 0000 0101 5
0000 0111 == 7
// eg.2 设置整数15的第2个二进制位为0
使用按位与方式:运算数n为 0000 1101 = 2,整数15为 0000 1111
0000 1101 13
& 0000 1111 15
0000 1101 == 13
// eg.3 设置整数a的中间4位取反,a = 0x10101101,运算数n应为多少?
使用按位异或方式:运算数n为 0000 0010 = 2,整数a为 1010 1101
0011 1100 n,60
^ 1010 1101 a,-83
1001 0001 == X,-111
本文总结自“狄泰软件学院”唐佐林老师《C语言入门课程》。
如有错漏之处,恳请指正。