一、操作符分类
1、算数操作符
+ - * / %
这些操作符跟数学运算基本一样。
“/”是做除法。当“/”左右两边的操作数都是整数时,执行的是整数除法;当两边的操作数至少有一个数为浮点数(小数)时,执行的是小数除法
“%”是算余数
2、移位操作符
<< >>
(1)“<<”左移操作符
①移的是内存中的2进制位
②a<<1的结果是移位之后的效果,但是a的值是不变的
a=a<<1,这个a的值是变的
③操作数必须是整数
(2)“>>”右移操作符
①移的是内存中的2进制位
②右移操作符分为:算数右移、逻辑右移
算数右移:右边丢弃,左边补原来的符号位
逻辑右移:右边丢弃,左边补0
大多数编译器上是算术右移
③操作数必须是整数
3、位操作符
& | ^
(1)& 按位与
对应的二进制位有0,则为0,两个同时为1,则为1
(2)| 按位或
对应的二进制位有1,则为1,两个同时为0,则为0
eg、不创建变量交换整数a,b
a = a ^ b
b = a ^ b
a = a ^ b
位操作符的操作数必须是整数
4、赋值操作符
=
赋值操作符可以连续使用,从右向左读
a = x = y + 1
复合赋值符
+= -= *= /= %= >>= <<= &= |= ^=
5、单目操作符
! - + &(取地址) sizeof ~ ++ -- * (类型)
(1)sizeof
“sizeof”后面的括号可以省略的,sizeof内部的表达式是不计算的
(2)~
“~”对一个数的二进制全部按位取反
(3) (类型)
“(类型)”是强制类型转换
eg、int a = (int)3.14
6、关系操作符
> >= < <= != ==
7、逻辑操作符
&& ||
“&&”逻辑与
从左往右判断,左边为假,右边不执行
“||”逻辑或
区分逻辑与和按位与 区分逻辑或和按位或
1 & 2---->0
1 && 2---->1
1 | 2----->3
1 || 2---->1
eg、
#include <stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
//i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
//打印的结果是
//a = 1
//b = 2
//c = 3
//d = 4
8、条件操作符(三目操作符)
exp1 ? exp2 : exp3
exp1表达式为真,exp2执行;exp1表达式为假,exp3执行
9、逗号表达式
exp1, exp2, exp3, ......expN
从左往右依次执行,整个表达式的结果是最后一个表达式的结果
10、下标引用、函数调用和结构成员
[ ] ( ) . ->
(1)[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
(2)( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数 的参数。
(3)访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
二、表达式求值
1、隐式类型转换
(1)整型提升
当进行运算时,如果要计算的两个操作数的数据类型不同,就要进行类型转化。如果要转换的操作数字节长度小于int类型的字节长度,那么就要进行整形提升。
整形提升是按照变量的数据类型的符号位来提升的。
(2)要整型提升的数据类型
char unsigned char short unsidned short
2、算术转换
如果某个操作符的各个操作数属于不同的类型,那么就要进行算术转换。
long double
double
float
unsigned long
int long
int unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。