一、算数操作符
+ 加
- 减
* 乘
/ 除
% 取模
需要注意几点:
- 除了 % 运算符两边的操作数只能是整数外,其余操作符可以是整数或者浮点数
- m % n 操作符得到的是 m 除以 n 的余数
- 当 / 两边的操作数是整数时,执行的是整数除法,m / n 得到的是 m 除以 n 的商
二、移位操作符
>> 左移操作符
<< 右移操作符
该操作符的说明中涉及到了整形在内存中的存储
移位操作符两边的操作数只能为整数
左移操作符:<<
规则:左边抛弃,右边补 0
a << b 表达式的结果为 a 的补码向左移动 b 位,并不会改变 a
在不超过存储范围的前提下左移n位有乘 2^n 的效果
>> 右移操作符
规则:
- 逻辑移位:右边抛弃,左边补 0
- 算数移位:右边抛弃,左边补左操作数的符号位,负数补 1 正数补 0
a >> b 表达式的结果为 a 的补码向右移动 b 位,并不会改变 a
博主以 VS2022 的编译器来举例,其编译器采用的是 算数移位
右移操作符具有除 2 的效果(这里指的是整数除法,得到的结果是商)
但是在算术右移中有两个例外:
- 1 右移时得到的是 0
因为 1 的补码是: 00000000 00000000 00000000 00000001 - -1 右移时得到的是 -1
因为 -1 的补码是:11111111 11111111 11111111 11111111
注意:移位操作符最好不要移动负数位,这是标准未定义的,取决于编译器
三、位操作符
& 按位与
| 按位或
^ 按位异或
~ 按位取反
该操作符的说明中涉及到了整形在内存中的存储
位操作符两边的的操作数只能是整数,并且不会改变操作数
-
& 按位与操作符
a & b 表达式的结果为 a 的补码和 b 的补码对应的二进制位进行 AND 运算,同为 1 则则该位为 1,有一个为 0 或者都为 0 则该位为 0 -
| 按位或操作符
a | b 表达式的结果为 a 的补码和 b 的补码对应的二进制位进行 OR 运算,同为 0 则该位为 0,有一个为 1 或者都为 1 则该位为 1 -
^ 按位异或操作符
a ^ b 表达式的结果为 a 的补码和 b 的补码对应的二进制位进行 异或 运算,同为 0 或同为1 则该位为 0,相异则该位为 1
- ~ 逻辑反操作符
~ 是单目操作符,只需要一个操作数,~ a 表达式的结果为 a 的补码对应的二进制位进行按位取反
四、赋值操作符
= 赋值操作符
= 赋值操作符
左边的操作数称为左值,右边的操作数称为右值
左值:可以存放数据的空间,如:变量,指针指向某个变量对其解引用
右值:常量,变量,表达式等
//a 和 p 都是变量,可以做为左值
int a;
int* p = &a;
a = 3;
*p = 2; *p 也可以作为左值
复合赋值符
+= 加等
-= 减等
*= 乘等
/= 除等
%= 取模等
>>= 左移等
<<= 右移等
&= 按位与等
|= 按位或等
^= 按位异或等
这里以 +=(加等)为例:
五、单目操作符
在单目操作符中,只需要一个操作数
! 逻辑反操作
~ 对一个数的补码按位取反
- 负值
+ 正值
++ 前置、后置
-- 前置、后置
sizeof 计算操作数的类型长度,单位为字节
& 取地址
* 间接访问操作符
(类型) 强制类型转换
-
!逻辑操作符中介绍
-
~ 位操作符中介绍
-
- 表示一个数值为负数
-
+ 表示一个数值为正数, 数值在不声明时默认为正数,一般不使用
-
++ 自增操作符、-- 自减操作符
分为 ++ 前置和后置 ++ 以及 – 前置和后置 –
这里以 ++(自增)为例:
-
sizeof 计算操作数的类型长度,单位为字节
-
& 取地址操作符
取出变量的地址,数组的地址,以及函数的地址
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 0;
int arr[5] = { 0 };
int* pa = &a; //取出 a 变量的地址,赋给【指向整形的整形指针 pa】
int(*parr)[5] = &arr; //取出数组 arr 的地址,赋给【指向 5 个元素,每个元素为 int 的数组指针 parr】
int (*padd)(int, int) = &Add; //取出函数 Add 的地址,赋给【指向参数为两个 int类型,返回值为 int 的函数指针 padd】
return 0;
}
- * 间接访问操作符
指针 pa 指向一块空间后,*pa 相当于这块空间
- (类型) 强制类型转换
将操作符的类型,强制转换为括号中的类型
#include <stdio.h>
int main()
{
//整数默认为 int 类型
char c = (char)10;
return 0;
}
六、关系操作符
如果两个操作数符合关系,表达式结果为 1,不符合关系,表达式结果为 0
注意:C语言中,非0 表示真,0 表示假
> 大于
>= 大于等于
< 小于
<= 小于等于
!= 不等于
== 等于
七、逻辑操作符
!逻辑非
&& 逻辑与
|| 逻辑或
-
!逻辑非操作符
-
操作数为真时(非0),表达式结果为假(0),操作数为假时,表达式结果为真(1)
-
&& 逻辑与操作符
两个操作数都为真时(非0),表达式结果为真(1),两个操作数有一个或都为假时(0),表达式结果为(0)
左操作数为假(0)时,不会在计算并判断右操作数的真假 -
|| 逻辑或操作符
两个操作数都为假时(0),表达式结果为假(0),两个操作数有一个或都为真时(非0),表达式结果为(1)
左操作数为真(非0)时,不会在计算并判断右操作数的真假
八、条件操作符
? : 条件操作符
exp1 ? exp2 : exp3
exp1 为真时(非0)整个表达式结果为 exp2,exp1 为假时(0),整个表达式结果为 exp3
九、逗号表达式
, 逗号表达式
exp1, exp2, exp3, …expn
逗号表达式,就是用逗号隔开的多个表达式,表达式从左向右依次执行。整个表达式的结果是最后一个表达式的结果
十、下标引用、函数调用和结构体成员访问
[ ] 下标引用
( ) 函数调用
. 结果体访问成员操作符
-> 结构体指针访问成员操作符
- [ ] 下标访问操作符
用来访问数组元素,操作数为 数组名 和 索引值
int arr[10]; //创建数组
arr[9] = 10; //[ ]的两个操作数是arr和9
-
( ) 函数调用操作符
用来调用函数,有一个或者多个操作数:第一个操作数是函数名,剩余的操作数是传递给函数的参数
-
. 结构体访问成员操作符
结构体.成员名, 访问该结构体的指定成员 -
-> 结构体指针访问成员操作符
-> 结构体指针->成员名,访问结构体指针指向的结构体的指定成员
十一、表达式求值
表达式求值时,当不同类型参与运算时,需要进行类型转换
- 隐式类型转换
- 在C语言中,整型参与运算时至少需要达到 int 类型的精度,所以表达式中的字符和短整型操作数在使用之前将被转换为普通整型
- 其他情况时采用寻常算术转换,下面列表中排名较低的类型将被转换为排名较高的类型
long double
double
float
unsigned long int
long int
unsigned int
int
操作符的类型相同之后,各部分的求值顺序由操作符的优先级和结合性决定
- 操作符的属性
相邻的操作符,先执行优先级高的操作符,如果相邻操作符优先级相同时,由他们的结合性决定
在分析一个复杂的表达式时,可以查阅操作符的优先级