C语言目录:
运算符:告诉程序执行特定的算术或逻辑操作的符号
表达式:利用运算符连接在一起的有意义、有结果的语句
- 表达式一定要有结果
按功能化划分:
按照参与运算符的个数划分:
单目运算符
如:i++
双目运算符
如:a+b
如:a>b ? 1 : 0;
不同优先级 的运算符,运算次序按照 优先级从高到低执行
相同优先级 的运算符,运算次序按结合性规定的方向执行
#include
int main(){
int a = 10;
int b = 5;
// 算术运算符的结合性和优先级
// 结合性: 左结合性, 从左至右
int c = 50;
result = a + b + c; // 15 + c; 65;
printf("%i\n", result);
// 优先级: * / % 大于 + -
result = a + b * c; // a + 250; 260;
printf("%i\n", result);
}
单目运算符,赋值运算符,三目运算符为右结合性;
其余为左结合性(从左向右看)
x = 2;
x+=x+=x-=1; //=> x = 4
y = x&1 == x%2; //=> y = 1
/*
*设x = 10 0&1 = 0 , x % 2 = 0 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 | , | 逗号运算符 | 表达式,表达式,... | 左到右 |
#include
int main(){
int a = 10, b = 20, c;
// ()优先级高于,和=, 先计算()中的内容
// c = (11,21);
// ()中是一个逗号表达式, 结果是最后一个表达式的值, 所以计算结果为21
c = (a + 1,b + 1);
printf("c = %d\n", c); // 21
}
#include
int main(){
int n = 1;
// ++在后, 先参与表达式运算, 再自增
// 表达式运算时为: 3 + 1;
int res = 3 + n++;
printf("res = %d\n", res); // 4
printf("n = %d\n", n); // 2
}
#include
int main(){
int n = 1;
// ++在前, 先自增, 再参与表达式运算
// 表达式运算时为: 3 + 2;
int res = 3 + ++n;
printf("res = %d\n", res); // 5
printf("n = %d\n", 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++;
用于计算一个变量、或常量、数据类型占用的内存字节数
sizeof(常量 or 变量);
sizeof(10); //sizeof 10;
char c = 'a';
sizeof(c); //sizeof c;
sizeof(数据类型);
sizeof(float);
sizeof是一个运算符,不是函数
sizeof
运算符优先级为2int a = 10;
double b = 3.14;
double res = sizeof(a+b);// sizeof a+b;
# sizeof 运算符优先级比+高,所以会先计算sizeof(a),再利用结果和b相加
//res = 7.14
优先级 | 符号 | 含义 | 表达式 | 结合性 | |
---|---|---|---|---|---|
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 取余 | 表达式%表达式 | |||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 |
如果参与运算的两个操作数都是整数,那么结果也是整数
如果参与运算的两个操作数有一个是浮点数,那么结果一定是浮点数
#include
int main(){
// 整数除以整数, 结果还是整数
printf("%i\n", 10 / 3); // 3
// 参与运算的任何一个数是小数, 结果就是小数
printf("%f\n", 10 / 3.0); // 3.333333
}
取余运算符,参与运算的两个操作数必须是整数,不能包含浮点数
取余运算结果的符号与被除数有关
#include
int main(){
// 被除数是正数结果就是正数,被除数是负数结果就是负数
result = 10 % 3;
printf("%i\n", result); // 1
result = -10 % 3;
printf("%i\n", result); // -1
result = 10 % -3;
printf("%i\n", result); // 1
}
取余运算符,被除数为0,结果为0
除法/取余运算,除数为0,没有意义
非零值都是 true
,只有零才是 false
关系运算符的运算结果只有两种:
true
false
# include
int main(){
//== 优先级小于 > ,所以先计算 >
int result = 10 == 5 > 3;//10 == 1 -> true
printf("%d\n",result);
}
# include
int main(){
// == 和 != 优先级一样,所以按照结合性
int res = 10 == 5 != 3;// 10 == true -> true
printf("%d\n",res);
}
无论是 float
还是 double
都有精度问题, 所以一定要避免利用 ==
判断浮点数是否相等
程序中所有数据都是以二进制形式存储,位运算符就是直接对整数在内存中的二进制操作
符号 | 名称 | 运算结果 |
---|---|---|
& | 按位与 | 同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
任何数和1进行&操作,得到这个数的最低位
1000
&0001
----
0000 // 结果为0, 代表是偶数
1011
&0001
----
0001 // 结果为1, 代表是奇数
9|5 = 13
1001
| 0101
----
1101
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("%d\n", S_IRUSR | S_IWUSR); // 384 // 110000000
相同整数异或为0,如 5^5=0
多个整数相异或的结果跟顺序无关,如 5^6^7 == 5^7^6
5^7^7=5
9^5 = 12
1001
^ 0101
----
1100
a = a^b;
b = b^a; // b = b^a^a = a;
a = b^a; // a = b^a^b = a^a^b = b;
~9 = -10
原码 0000 1001
补码 1111 0110
转为十进制 0000 1001+1 = 0000 1010 = -10
2<
:相当于乘2的n次方
高位舍弃,低位补0,高位丢弃,但符号位也会丢弃,造成正负性改变
2<<1; //相当于 2 *= 2 // 4
0010
<<0100
2<<2; //相当于 2 *= 2^2; // 8
0010
<<1000
2>>n
:相当于除以2的n次方
正数时,符号位为0,最高位补0
负数时,符号位为1,最高位是补0 或 是补1取决于编译系统
优先级 | 符号 | 名称 | 符号 | 结合性 | |
---|---|---|---|---|---|
2 | ! | 逻辑非 | !表达式 | 右结合性 | 单目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
! 条件A;
运算结果:
!true = false;
!false = true;
条件A && 条件B;
判断过程
true
false
条件A || 条件B;
判断过程
false
true
false