操作符
原码、反码、补码
存储到内存中的是补码
正整数原码反码补码都相同
原码
反码:符号位不变,其他位按位取反
补码:反码+1
移位操作符
移位操作符移的是补码
32位
10000000000000000000000000010000
右移操作符:
计算机一般用的是算数右移
1.算术右移:右边丢弃,左边补符号位,右移一位有除2效果
10000000000000000000000000001000
2.逻辑右移:右边丢弃,左边补0
00000000000000000000000000001000
左移操作符:左边丢弃,右边补0
位操作符
注意:补码运算
-
按位与&
- 0&0=0
- 0&1=0
- 1&1=1
00101101
10110110
&00100100
- 按位或 |
- 0|0=0
- 0|1=1
- 1|1=1
00101101
10110110
|10111111
-
按位异或^ 相同为0,相异为1
- 0^0=0
- 0^1=1
- 1^1=0
00101101
10110110
^ 10011011
不创建临时变量,交换两个int
- method 1
1 | int main() |
- method 2
1 | int main() |
a与b异或得到c
c与a异或可得到b
c与b异或可得到a
不会溢出
exercise 1
练习:求一个整数的二进制表示中“1”的个数
1 |
|
1 | int main() |
赋值操作符
=
支持连续赋值(不建议)
a = x = y + 1; <=> x = y + 1; a = x;
复合赋值符
+= -= /= *= %= >>= <<= |= &= ^=
单目操作符
只有一个操作数
! 逻辑反操作
非0为真,0为假
! 是真为假,假为真
!0=1,1为真,真不一定都为1
- 负值
- 正值
& 取地址操作符
- 解引用操作符(间接访问操作符)
sizeof 操作数的类型长度(以字节为单位)
32位 int 4 char 1 char* 4
可以写 sizeof(int) 数组:sizeof(int [10])
如果为变量,可以省略括号,如 sizeof a
如果为类型,不可省略括号,如 sizeof(int)
short s = 0;
int a = 10;
printf(“%d\n”, sizeof(s = a + 5); 2 s是short
printf(“%d\n”, s); 0 sizeof中表达式不会进行真实运算
~ 对一个数的二进制按位取反
内存中对补码取反
原码0000000000000000000000000000000
取反1111111111111111111111111111111(补码)
10000000000000000000000000001(原码) – -1
a = a | (1 << n) 可以使a的指定二进制位为1
a = a & ~(1 << n) 可以使a的指定二进制位位0
++ – 前置,后置++ –
a 前置表示先后使用
a 后置表示先使用后
(类型) 强制类型转换
(int) 3.14
关系操作符
= < <= != ==
逻辑操作符
&& 逻辑与
|| 逻辑或
3 && 5 = 1
0 && 5 = 0
0 || 5 = 1
0 || 0 = 0
exercise 2
程序输出的结果是什么?
1 |
|
条件操作符(三目操作符)
exp1 ? exp2 : exp3
如果exp1为真,则exp2执行,且执行结果为整个表达式的结果
如果exp1为假,则exp3执行,且执行结果为整个表达式的结果
逗号表达式
exp1,exp2,exp3,…,expn
从左向右执行,整个表达式的结果是最后一个表达式的结果
下标引用操作符
[ ]
函数调用操作符
( )
结构成员操作符
. 结构体.成员名
-> 结构体指针->成员名
1 | struct stu |
表达式求值
- 隐式类型转换
C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
原因:CPU内整型运算器的操作数的字节长度一般为int长度
1 | int main() |
- 算术转换
也属于隐式转换的一种
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
- 操作符属性
- 操作符的优先级
- 操作符的结合性
- 是否控制求值顺序