1、分类
运算符类型 | 运算符 | 运算顺序 |
---|---|---|
下标引用 | [ ] | 自左向右 |
函数调用 | ( ) | 自左向右 |
结构成员访问 | . | 自左向右 |
指针成员访问 | -> | 自左向右 |
单目操作符 | ! sizeof ++ – (type) * & ~ | 自右向左 |
算术操作符 | + - * / % | 自左向右 |
移位操作符 | << >> | 自左向右 |
关系操作符 | > >= < <= == != | 自左向右 |
位操作符 | & ^ | | 自左向右 |
逻辑操作符 | && || | 自左向右 |
条件操作符 | ? : | 自左向右 |
赋值操作符 | = += -= *= /= | 自右向左 |
逗号表达式 | , | 自左向右 |
1.1单目操作符
所谓单目操作符,即只有一个操作数。
!逻辑反操作 &取地址 sizeof操作数的字节长度(为类型时必须加括号,变量可有可无)
~一个数的二进制按位取反 ++ -- 后置:先使用在±1;前置:先±1再使用 *解引用操作符
(类型)强制转换类型
1.2算术操作符
除法:整形的除法:1/2=0;
浮点数的除法:1.0/2=0.5; 1/(2*1.0)=0.5;
%:取模操作符,计算整除后的余数,两端必须是整数
1.3移位操作符
移位操作符的操作数只能是整数
整数在二进制中的表示有三种,分别为原码、反码和补码。计算机中均数值均以二进制的补码形式进行表示和存储。对于无符号的整数,所有位都是数值位;有符号的整数,最高位是符号位,其余是数值位
正数的原码、补码和反码均相同,负数的补码由原码符号位不变,其他位按位取反再加一得到
左移操作符:<<
右移操作符:>>
逻辑右移:右边丢弃,左边补0;
算术右移:右边丢弃,左边补原值符号位;绝大多数编译器采用算术右移
1.4关系操作符
> >= < <= == != 其中,== 与 != 的优先级低于其他关系运算符的优先级
"abc"=="abcdef"; 这样是在比较两个字符串首字符的地址
1.5位操作符
& 按位与:逐位比较两个运算对象的二进制的补码,只有两个数的补码的对应位均为1是结果的对应位才为1;如果对应位为1,则保留原数该位的数字。某位改成0可以用&
| 按位或:逐位比较两个运算对象的二进制的补码,两个数的补码的对应位有1则结果的对应位为1 ;如果对应位为0,则保留原数该位的数字。某位改成1可以用|
& 的优先级高于 ^ 的优先级高于 | 的优先级
①a|0=a
^ 按位异或:,逐位比较两个运算对象的二进制的补码,两个数的补码对应位不相同则结果的对应位为1
① a^a=0; 0^a=a
②异或支持交换律,a^b^a=a^a^b=b
使用:不创建临时变量,实现两个数的交换
int main()
{
int a=3;
int b=5;
a=a+b;
b=a-b;
a=a-b;
}
但是当数值过大时 ,可能会造成数值溢出;
int main()
{
int a=3;
int b=5;
a=a^b;
b=a^b;
a=a^b;
}
1.6逻辑操作符
逻辑与 && a++&&b++&&++c:当a=0时,则表达式结果一定为0,后面的运算不再计算
逻辑或 || a++||b++||c++:当a!=0时,则表达式结果一定为真,不再计算后面部分
1.7条件操作符(三目操作符)
表达式1 ? 表达式2 : 表达式3;
表达式1若为真,则表达式2进行计算,整个表达式的结果为表达式2的结果
表达式1若为假,则表达式3进行计算,整个表达式的结果为表达式3的结果
1.8赋值符
连续赋值:x=y=a+1;等效于 y=a+1;x=y;
复合赋值符:+= -= *= /= %= <<= >>= &= |= ^=
a=a+5;等效于a+=5;
1.9逗号表达式
exp1,exp2,exp3,......expn
用逗号隔开的多个表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果
下标引用操作符
int main()
{
int arr[10]={0};
arr[7]=8;
7[arr]=9;
//arr[7]--->*(arr+7)--->*(7+arr)--->7[arr]
}
从注释可以得到arr[7]与7[arr]等价
表达式求值
表达式的求值一部分有 优先性、结合性和是否控制求值顺序决定;此外,求值过程中操作数还可能会进行类型的转换
隐式类型转换
C语言中的整形算术运算总是至少以默认的整形类型的精度来进行计算的,为了达到这个精度,表达式中的字符和短整型在使用之前都换被转换成普通整形,这种转换就称为整形提升。
通过按照数据类型的符号位来进行提升,在高位补符号位直到32个比特位,无符号类型则补0;
下图中存入b的补码应为 01111110
实例
算术转换
int->unsigned int ->long int ->unsigned long int ->float->double ->long double
操作符的操作数类型会向右转换成相同的类型进行计算。