操作符
一 . 算数操作符
常用的算数操作符:
+ - * / %
- 除了%操作符,其余几个操作符都是既适用于浮点型又适用于整数类型。
- 当 / 操作符的两个操作数是整数时,它执行整数运算,只要有浮点数则执行浮点数除法。
【如果整除运算的任一操作数为负值,运算结果由编译器定义的】
- % 为取模操作符,其两个操作数必须为整数,而返回的值是整除之后的余数。
二 . 移位操作符
左移位操作符 << 右移位操作符 >>
- 移位操作是把一个值的二进制位向左或向右移动。
左移三位举例
0 1 1 0 1 1 0 1 //移位前
0 1 1 0 1 1 0 1 用0补充 //左移三位数
0 1 1 0 1 0 0 0 //最终结果
- 左移一位,相当于数值乘2;右移一位,相当于除以2。
- 在 左 移位中,值最左边的几位被丢弃,右边多出来的几个空位由 0 补齐。
- 在 右 移位中,有两种方案:(二者只有在操作符是负值时才不一样)
- 逻辑移位:左边移入的位用0填充;
- 算数移位:左边移入的位由原先该值的符号位决定,符号位为1 则移入的位均为1,符号为0,移入的位均为0。
- 左操作数的值将移动由右操作数指定的位数,两个操作数都必须是整型类型。
警告:注意类似这种形式的移位
a<<-5 这类移位行为是未定义的,由编译器决定,因此应该避免这种类型的移位。
补充:正数的原码,反码,补码相同;
负数的补码是原码取反加一。
三 . 位操作符
位操作符有:
& // 按位与 如果两个位都为1,结果为1;否则结果为0
| // 按位或 如果两个位都是0,结果为0;否则结果为1
^ // 按位异或 如果两个位不同,则结果为1;如果两个位相同,结果为0
注意 他们的操作数必须为整数。
按位与:m是一个二进制数,m&1的结果即为m的最后一位
- 奇数位和 + 偶数位和 == 二进制数
四 . 赋值操作符
=
求值顺序是从右往左
它可以连续赋值,但是不太提倡
- x=y=z+3
- {x=z+3;
y=z+3;} 第2个显然比第1个清晰
五 . 复合赋值符
+= -= -+ *= /= %= <<= >>= &= ^= |= (类型)
用+=来举例具体讨论
a+=b 相当于 a=a+b 其余操作符与它相似
六 . 单目运算符
C语言中只接受一个操作数的操作符 :
! 逻辑反操作 操作数为真,结果为假;操作数为假,结果为真。实际上产生一个整型结果,0或1.
~ 求补操作 对整型操作数进行操作 原先为1的位变为0,原先为1的位变为0
- 产生操作数的负值
& 产生操作数的地址
* 间接访问操作符,与指针一起使用,用于访问指针所指向的值
sizeof 判断操作数的类型长度,以字节为单位表示,操作数既可以是个表达式,也可以是(类型名)
(类型) 强制类型转换,用于把表达式的值转换为另外的类型
++ -- 这两个操作符都有两个变型,前缀形式(++i)和后缀形式 (i++)
前缀形式:操作数的值被增加或减小,但表达式的值就是操作数增加(减小)后的值
后缀形式:操作数的值仍被增加或减小,但表达式的值是操作数增加(减小)前的值
七 . 关系操作符
> >= < <= != 测试不相等 == 测试相等
- 如果两端的操作数符合操作符指定的关系,表达式结果是1,如果不符合,结果是0
- 关系操作符的结果是整型值,所以它可以赋值给整型变量
- 注意,在以后编写程序时一定注意区分 赋值= 和 相等==
八 . 逻辑操作符
&& 逻辑与 (1)&&( 2 ) 如果表达式1是真的,再对表达式2求值;
如果表达式1是假的,对表达式2没必要再求值,整个式子则为假
|| 逻辑或 对表达式1求值,若为真,则不必要求后面的,整个式子结果已经确定
以上行为被称为 短路求值
- 警告 区分按位与和逻辑与
区分按位或和逻辑或
二者区别——逻辑操作符具有短路性质;
——逻辑操作符用于测试零值和非零值,位操作符用于比较它们的操作数中对应的位。
九 . 条件操作符
条件操作符接受三个操作数,并且会控制子表达式的求值顺序。
exp1 ? exp2 : exp3
首先算exp1,若它的值为非0值,即为真,那么整个表达式的值为exp2,对exp3不会求值;
但是如果exp1的值为假,那么不对exp2 求值,整个表达式的值为exp3。
十 . 逗号表达式
exp1,exp2,exp3,、、、expN
这些表达式自左向右逐个进行求值,整个逗号表达式的值就是最后一个表达式的值。
十一 . 下标引用,函数调用和结构成员
- 下标引用操作符 [ ]
操作数:一个数组名 + 一个索引值 // arr[9]=1;
- 函数调用操作符 ()
操作数:接受一个或者多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数
- 访问一个结构的成员
. 结构体. 成员名
.作用于结构体变量
->结构体指针->成员名
->作用于结构体指针
表达式求值
表达式求值的顺序一般由操作符的优先性和结合性决定;
有些操作数则需要转换为其他类型。
隐式类型转换
C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获取这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通类型,这种转换称为 整型提升。
例如
char a,b,c;
...
a=b+c; //b和c的值被提升为普通类型,然后再执行加法运算,加法运算完成后结果被截断,再存储于a中
算术转换
如果某个操作符的各个操作数属于不同类型。那么除非其中一个操作数转换为另外一个操作数的类型,否则操作无法进行。l
下面的层次体系称为寻常算术转换:
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么它首先将转换为另一个操作数的类型然后进行操作。
操作符属性
同一优先级的运算符,运算次序由结合方向所决定。
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符