目录
一、算术操作符
二、移位操作符
1.左移操作符
?2.右移操作符
三、位操作符
四、赋值操作符
五、单目操作符
六、关系运算符
七、逻辑操作符
八、条件操作符
九、逗号表达式
十、下标引用、函数调用和结构成员
十一、表达式求值
1.隐式类型转换
2.算术转换
一、算术操作符
+? -? *? /? %
- 除了%操作符之外,其他几个操作数都可以作用于整数和浮点数
- 对于 / 操作符,如果两个操作数都是整数,执行整数除法,而只要两端有一个操作数是浮点数,那么执行的就是浮点数除法;
- % 操作符的两个操作数必须是整数,返回整除后的余数。
二、移位操作符
<<? 左移操作符
>>? 右移操作符
【注意】:
- 移位操作符的操作数只能是整数;
- 对于移位操作符,不要移动负数位
移位操作符移动的是二进制位
所以这里又要讲到整数在计算机中的存储,我们都知道数据在计算机中是以二进制的方式存储的
而整数有三种二进制表示形式:原码、反码、补码
正整数,原码、反码、补码相同
负整数,原码、反码、补码不同 ,需要进行计算,
计算的规则:原码符号位不变,其余位按位取反就是反码;反码加一得到补码
1.左移操作符
移位规则:左边抛弃,右边补0
?2.右移操作符
移位规则:
1.无符号整数:(逻辑右移)
? ? ?左边补0,右边丢弃
2.有符号整数:(算术右移)
? ? ?左边补符号位,右边丢弃
三、位操作符
&? ?按位与
?|? ?按位或
?^??按位异或
~ ? 按位取反
这里的“位” 指的是二进制位
按位与& :对应的二进制位有0,则为0,全1才为1;注意与取地址&区分
按位或 |? :对应的二进制位有1,则为1,全0才为0;
按位异或^ :对应的二进制位相同,则为0,相异才为1;
按位取反~? :二进制位为0则变为1,如果二进制为1则变为0。
注意:对位操作实际上是对存储在内存上的二进制位进行操作的,然而整数在内存上存储的是其二进制的补码形式,所以对位操作,也就是对二进制的补码进行的操作。 ?
补充一道经典的题:
不能创建临时变量(第三个变量),实现两个数的交换:
方法一:加减法
a = a + b;
b = a - b;
a = a - b;
这样就解决了,但是有不好的地方,如果a, b 很大,就可能会导致溢出,所以还有一种方法,就是利用异或法
方法二:异或法
a = a ^ b;
b = a ^ b;
a = a ^ b;
这样就交换完成了,但是在实际运用当中,习惯定义第三个变量来实现两个数的交换,因为,上面的代码可读性都不高!? ?
四、赋值操作符
=
左值与右值
左值:是可以放在等号左边的,一般是一块空间;
右值:是可以放在等号右边的,一般是一个值或是一块空间的内容
int a = 10; // a就是左值,代表的是一块空间
a = 20;// 20就是右值,代表一个值
? +=? ?-=? ?*=? ?/=? ?&=? ?^=? ?!=? ?>>=? ?<<=
复合赋值操作符。如:a+=5等价于a=a+1
五、单目操作符
- ! ? ? ? ? ? ? ? ?逻辑反操作
- - ? ? ? ? ? ? ? ?负值
- + ? ? ? ? ? ? ? 正值
- & ? ? ? ? ? ? ? 取地址
- sizeof ? ? ? 操作数的类型长度(以字节为单位)
- ~ ? ? ? ? ? ? ? 对一个数的二进制按位取反
- -- ? ? ? ? ? ? ? 前置、后置--
- ++ ? ? ? ? ? ? 前置、后置++
- * ? ? ? ? ? ? ? ?间接访问操作符(解引用操作符)
- (类型) ? ? ? 强制类型转换
?
单目操作符:操作数只有一个,什么叫操作数呢?比如:2 + 3 --> 2和3就是操作数,由于‘+’有两个操作数,数以叫双目运算符。
++? ?--? ?
以前置、后置++为例
前置为先自增再使用,后置为先使用再自增
举个例子
?
(类型): 强制类型转换操作符将表达式的值转换为所需的数据类型
【说明】:
(1)类型名和表达式都必须加括号(单个变量可以不加括号)。 例如,“(int)(x+y)” 表 示把x+y的结果转换成int类型,而“(int)x+y” 表示把x转换成int之后再与y相加。
(2)强制转换不改变数据说明时对该变量定义的类型。例如,"(double)a" 只是将变量a的值转换成一个double型的中间量,a的数据类型并未转换成double型。 ?
六、关系运算符
- >
- >=
- <
- <=
- !=? ? ? ?用于测试“不相等”
- ==???? ?用于测试“相等”
七、逻辑操作符
&&? ?逻辑与
||??? ? 逻辑或
!? ??逻辑非
&&:? ?逻辑与---“并且”? ?全为真才为真
||???:? ?逻辑或---“或者”? ?有一个为真就为真?
!? :? ?如果a为真,则!a为假
说明:C语言中用0表示假,非0表示真 ,注意是非0表示真,即使是-1也表示真。
八、条件操作符
exp1 ? exp2 : exp3
条件运算符,又称为三目运算符,表达式1为真,则计算表达式2的值,跳过表达式3,也就是说表达式2的结果就是整个表达式的结果;反之,若表达式1为假,跳过表达式2,直接计算表达式3的值,也就是说表达式3的结果就是整个表达式的结果。
九、逗号表达式
exp1,exp2,exp3...expN
逗号表达式就是用逗号隔开的表达式
注意:逗号表达式会从左向右依次计算,整个表达式的结果是最后一个表达式的结果
十、下标引用、函数调用和结构成员
?[ ]? ? ? ? ?下标引用操作符
?()? ? ? ? ? ?函数调用操作符
.? ? ??->? ? 访问结构成员操作符
[ ]? ?下标引用操作符
操作数:数组名+索引值,如arr[10]
?()? ?函数调用操作符
接收一个或多个操作数:第一个操作数为函数名,剩余操作数为传给函数的参数。
.? ? ??->? ? 访问结构成员操作符
访问一个结构的成员:
?结构体变量 . 结构体成员;
?结构体指针->成员名
十一、表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定
相邻两个操作符先执行哪个,取决于他们的优先级。如果两者优先级相同,取决于他们的结合性。
同样,有些表达式的操作数在求值的过程中可能需要转化为其他类型
1.隐式类型转换
由于计算机的CPU通常是以4个字节为单位从内存中读写数据,所以,为了硬件上实现方便,表达式中各种长度可能小于int 长度的整型值,都必须先转换成int 或 unsigned int?,然后才能送入CPU去执行运算。比如char、short这种类型数据都需要注意整形提升的问题。
那么如何理解整形提升呢?
整形提升是按照变量的数据类型的符号位来提升的(补其符号位!)?
例子
#include<stdio.h>
?
int main()
{
?? ?char c = 1;
?? ?printf("%u\n", sizeof(c));//输出1
?? ?printf("%u\n", sizeof(+c));//输出4
?? ?printf("%u\n", sizeof(-c));//输出4
?? ?return 0;
}
为什么呢?
c 只要参与表达式运算了,就会发生整形提升
2.算术转换
如果某个操作符的各个操作数属于不同的类型,那么就要将其中一个操作数转换为另一个操作数的类型,在进行计算。
long double
double
float
unsigned long int
long int?
unsigned int
int
如果某个操作数的类型在表中排序较低,那么就要将其转换为另一个排序较高的操作数的类型后执行运算
【注意】
算术转换要合理,否则会有一些潜在问题。
float f=3.14;
int a=f;//隐式转换,会有精度丢失
|