操作符分类
- 算术操作符
- 移位操作符
- 位操作符
- 赋值操作符
- 单目操作符
- 关系操作符
- 逻辑操作符
- 条件操作符
- 逗号表达式
- 下标引用、函数调用和结构成员
算术操作符:
+ - * / %
除了 % 操作符,其他几个操作符可以作用于整数和浮点数
% 操作符的两个操作数必须是整数,返回值是余数;
对于 / 操作符,如果两个操作数都为整数,执行整数除法(结果为整数),只要有浮点数就执行浮点数除法
移位操作符(只能作用于整数)
移动的是二进制补码
左移 <<
- 左边丢弃,右边补0
右移 >>
- 逻辑右移
- 右边丢弃,左边补0
- 算术右移
- 右边丢弃,左边用原该值的符号位填充
位操作符(只能作用于整数)
& //按位与 (只要有一个为 0 则为 0,两个都为 1 才是 1)
//统计二进制中1的个数
for(i=0;i<32;i++)
{
if(1==((num >> i)&1)
count++;
}
| //按位或 (只要有一个为 1 则为 1,两个都为 0 才是 0)
^ //按位异或(对应的二进制位相同为 0 ,相异为 1 )
//临时变量
tmp=a;
a=b;
b=tmp;
//加减法,可能溢出
a=a+b;
b=a-b;
a=a-b;
//异或,效率低,可读性差
a=a^b;
b=a^b;
a=a^b;
赋值操作符
=
复合赋值符
+= -= *= /= %=
>>= <<= &= |= ^=
单目操作符(只有一个操作数)
! 逻辑反操作(真变假,假变真)
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(字节)
~ 对一个数的二进制位按位取反
-- 自减
++ 自加
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
关系操作符
> >= < <= != ==
逻辑操作符
&& 逻辑与(左边如果是假,右边不管是什么都不运算)
|| 逻辑或(左边如果是真,右边不管是什么都不运算)
条件操作符(三目运算符)
exp1 ? exp2 : exp3
exp1 为真,则整个表达式的结果为exp2
exp1 为假,则整个表达式的结果为exp3
逗号表达式
exp1,exp2,exp3,......expN
逗号表达式,就是用逗号隔开多个表达式,从左往右依次执行,整个表达式的结果是最后一个表达式的结果
int a=1;
int b=2;
int c=(a>b,a=b+10,a,b=a+1);
下标引用,函数调用和结构成员
[ ] 下标引用操作符 操作数:一个数组名 + 一个索引值 arr[10]
( ) 函数调用操作符 操作数:函数名 + 参数 函数名(参数)
访问结构体成员
. 结构体.成员名
-> 结构体指针->成员名
表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
隐式类型转换
- 整型提升
- 算术转换
整型提升:
C的整型算术运算总是以缺省整型类型的精度来进行的
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
实例:
char a,b,c;
c = a + b;
a和b的值被提升为普通整型,再执行加法运算,加法运算完成后,结果将被截断,然后再存储于c中
如何进行整型提升:
按照变量的数据类型的符号位来提升
//负数的整型提升
高位补充符号位 1
char c = -1;
补码:11111111————整型提升:11111111 11111111 11111111 11111111
//正数的整型提升
char c = 1;
补码:00000001———整型提升:00000000 00000000 00000000 00000001
高位补充符号位 0
算数转换:
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行,下面的层次体系称为寻常算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另一个操作数的类型后执行运算
操作符的属性
复杂表达式的求值有三个影响的因素
- 操作符的优先级
- 操作符的结合性
- 是否控制求值顺序
优先级相同,则取决于结合性