4.1.1 分类运算符:告诉程序执行特定的算术或逻辑操作的符号
表达式:利用运算符连接在一起的有意义、有结果的语句
- 表达式一定要有结果
按功能化划分:
- 算术运算符
- 赋值运算符
- 关系运算符
- 逻辑运算符
- 位运算符
按照参与运算符的个数划分:
-
单目运算符
如:i++
-
双目运算符
如:a+b
-
三目运算符
如:a>b ? 1 : 0;
不同优先级 的运算符,运算次序按照 优先级从高到低执行
相同优先级 的运算符,运算次序按结合性规定的方向执行
#includeint main(){ int a = 10; int b = 5; // 算术运算符的结合性和优先级 // 结合性: 左结合性, 从左至右 int c = 50; result = a + b + c; // 15 + c; 65; printf("%in", result); // 优先级: * / % 大于 + - result = a + b * c; // a + 250; 260; printf("%in", result); }
单目运算符,赋值运算符,三目运算符为右结合性;
其余为左结合性(从左向右看)
x = 2; x+=x+=x-=1; //=> x = 4 y = x&1 == x%2; //=> y = 1 a = b = c = 1; ++a||++b&&++c; //a = 2,b = 1,c = 1;
| 优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
|---|---|---|---|---|---|
| 1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | |
| () | 圆括号 | (表达式)/函数名(形参表) | |||
| . | 成员选择(对象) | 对象.成员名 | |||
| -> | 成员选择(指针) | 对象指针->成员名 | |||
| 2 | - | 符号运算符 | -表达式 | 右到左 | 单目运算符 |
| (类型) | 强制类型转换 | (数据类型)表达式 | |||
| ++ | 自增运算符 | ++变量名/变量名++ | |||
| -- | 自减运算符 | --变量名/变量名-- | |||
| * | 取值运算符 | *指针变量 | |||
| & | 取地址运算符 | &变量名 | |||
| ! | 逻辑非 | !表达式 | |||
| ~ | 按位取反 | ~表达式 | |||
| sizeof | 长度运算符 | sizeof(表达式) | |||
| 3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
| * | 乘 | 表达式*表达式 | |||
| % | 取余 | 表达式%表达式 | |||
| 4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
| - | 减 | 表达式-表达式 | |||
| 5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
| >> | 右移 | 变量>>表达式 | |||
| 6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
| >= | 大于等于 | 表达式>=表达式 | |||
| < | 小于 | 表达式<表达式 | |||
| <= | 小于等于 | 表达式<=表达式 | |||
| 7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
| != | 不等于 | 表达式!=表达式 | |||
| 8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
| 9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
| 10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
| 11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
| 12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
| 13 | ?: | 条件运算符 | 表达式1?表达式2:表达式3; | 右到做 | 三目运算符 |
| 14 | = | 赋值运算符 | 变量=表达式 | 右到左 | |
| /= | 除后赋值 | 变量/=表达式 | |||
| *= | 乘后赋值 | 变量*=表达式 | |||
| %= | 取余后赋值 | 变量%=表达式 | |||
| += | 加后赋值 | 变量+=表达式 | |||
| -= | 减后赋值 | 变量-=表达式 | |||
| <<= | 左移后赋值 | 变量<<=表达式 | |||
| >>= | 右移后赋值 | 变量>>=表达式 | |||
| &= | 按位与后赋值 | 变量&=表达式 | |||
| ^= | 按位异或后赋值 | 变量^=表达式 | |||
| |= | 按位或后赋值 | 变量|=表达式 | |||
| 15 | , | 逗号运算符 | 表达式,表达式,... | 左到右 |
#include4.3 自增自减int main(){ int a = 10, b = 20, c; // ()优先级高于,和=, 先计算()中的内容 // c = (11,21); // ()中是一个逗号表达式, 结果是最后一个表达式的值, 所以计算结果为21 c = (a + 1,b + 1); printf("c = %dn", c); // 21 }
- 前缀表达式:++x, --x;表示先自增再运算
- 后缀表达式:x++, x–;表示先运算再自增
#includeint main(){ int n = 1; // ++在后, 先参与表达式运算, 再自增 // 表达式运算时为: 3 + 1; int res = 3 + n++; printf("res = %dn", res); // 4 printf("n = %dn", n); // 2 } #include int main(){ int n = 1; // ++在前, 先自增, 再参与表达式运算 // 表达式运算时为: 3 + 2; int res = 3 + ++n; printf("res = %dn", res); // 5 printf("n = %dn", n); // 2 }
自增、自减运算只能用于单个变量,只要是标准类型的变量(整型、实型还是字符型变量),但不能用于表达式或常量
- 错误用法:++(a+b); 5++;
int i = 10; int b = i++; // 不推荐 或者 int b = ++i; // 不推荐 或者 int a = 10; int b = ++a + a++; // 不推荐 int i = 10; int b = i; // 推荐 i++; 或者; i++; int b = i; // 推荐 或者 int a = 10; ++a; int b = a + a; // 推荐 a++;4.4 sizeof
用于计算一个变量、或常量、数据类型占用的内存字节数
sizeof(常量 or 变量);
sizeof(10); //sizeof 10; char c = 'a'; sizeof(c); //sizeof c;
sizeof(数据类型);
sizeof(float);
sizeof是一个运算符,不是函数
- sizeof 运算符优先级为2
int a = 10; double b = 3.14; double res = sizeof(a+b);// sizeof a+b; # sizeof 运算符优先级比+高,所以会先计算sizeof(a),再利用结果和b相加 //res = 7.144.5 算数运算符
| 优先级 | 符号 | 含义 | 表达式 | 结合性 | |
|---|---|---|---|---|---|
| 3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
| * | 乘 | 表达式*表达式 | |||
| % | 取余 | 表达式%表达式 | |||
| 4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
| - | 减 | 表达式-表达式 |
-
如果参与运算的两个操作数都是整数,那么结果也是整数
-
如果参与运算的两个操作数有一个是浮点数,那么结果一定是浮点数
#include
int main(){ // 整数除以整数, 结果还是整数 printf("%in", 10 / 3); // 3 // 参与运算的任何一个数是小数, 结果就是小数 printf("%fn", 10 / 3.0); // 3.333333 } -
取余运算符,参与运算的两个操作数必须是整数,不能包含浮点数
取余运算结果的符号与被除数有关
#include
int main(){ // 被除数是正数结果就是正数,被除数是负数结果就是负数 result = 10 % 3; printf("%in", result); // 1 result = -10 % 3; printf("%in", result); // -1 result = 10 % -3; printf("%in", result); // 1 } -
取余运算符,被除数为0,结果为0
-
除法/取余运算,除数为0,没有意义
非零值都是 true ,只有零才是 false
关系运算符的运算结果只有两种:
- 条件成立,结果为 true
- 条件不成立,结果为 false
# includeint main(){ //== 优先级小于 > ,所以先计算 > int result = 10 == 5 > 3;//10 == 1 -> true printf("%dn",result); }
# includeint main(){ // == 和 != 优先级一样,所以按照结合性 int res = 10 == 5 != 3;// 10 == true -> true printf("%dn",res); }
无论是 float 还是 double 都有精度问题, 所以一定要避免利用 == 判断浮点数是否相等
4.7 位运算符程序中所有数据都是以二进制形式存储,位运算符就是直接对整数在内存中的二进制操作
| 符号 | 名称 | 运算结果 |
|---|---|---|
| & | 按位与 | 同1为1,有0则0 |
| | | 按位或 | 同0位0,有1为1 |
| ^ | 按位异或 | 同0异1 |
| ~ | 按位取反 | 0变1,1变0 |
<| 按位左移 | 乘以2的n次方 | |
| >>n | 按位右移 | 除以2的n次方 |
9&5 = 1
1001
& 0101
----
0001
a. 判断奇偶
任何数和1进行&操作,得到这个数的最低位
1000
&0001
----
0000 // 结果为0, 代表是偶数
1011
&0001
----
0001 // 结果为1, 代表是奇数
4.7.2 按位或
9|5 = 13
1001
| 0101
----
1101
a. 权限设置
enum Unix {
S_IRUSR = 256,// 100000000 用户可读
S_IWUSR = 128,// 10000000 用户可写
S_IXUSR = 64,// 1000000 用户可执行
S_IRGRP = 32,// 100000 组可读
S_IWGRP = 16,// 10000 组可写
S_IXGRP = 8,// 1000 组可执行
S_IROTH = 4,// 100 其它可读
S_IWOTH = 2,// 10 其它可写
S_IXOTH = 1 // 1 其它可执行
};
// 假设设置用户权限为可读可写
printf("%dn", S_IRUSR | S_IWUSR); // 384 // 110000000
4.7.3 按位异或
相同整数异或为0,如 5^5=0
多个整数相异或的结果跟顺序无关,如 5^6^7 == 5^7^6
- 同一数异或另外一个数两次,结果还是那个数,如 5^7^7=5
9^5 = 12
1001
^ 0101
----
1100
a. 交换两个数的值
a = a^b; b = b^a; // b = b^a^a = a; a = b^a; // a = b^a^b = a^a^b = b;4.7.4 按位取反
~9 = -10 原码 0000 1001 补码 1111 0110 转为十进制 0000 1001+1 = 0000 1010 = -104.7.5 按位左移
2<
高位舍弃,低位补0,高位丢弃,但符号位也会丢弃,造成正负性改变
2<<1; //相当于 2 *= 2 // 4 0010 <<0100 2<<2; //相当于 2 *= 2^2; // 8 0010 <<10004.7.6 按位右移
2>>n :相当于除以2的n次方
正数时,符号位为0,最高位补0
负数时,符号位为1,最高位是补0 或 是补1取决于编译系统
4.8 逻辑运算符| 优先级 | 符号 | 名称 | 符号 | 结合性 | |
|---|---|---|---|---|---|
| 2 | ! | 逻辑非 | !表达式 | 右结合性 | 单目运算符 |
| 11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
| 12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
! 条件A;
运算结果:
- !true = false;
- !false = true;
条件A && 条件B;
判断过程
- 条件A为真,则接着判断条件B,也真,则表达式为 true
- 条件A为假,则不执行B,则表达式为 false
条件A || 条件B;
判断过程
- 条件A为假,且条件B为假,则表达式为 false
- 条件A为假,条件B为真,则表达式为 true
- 条件A为真,则不会执行条件B,则表达式为 false



