算数操作符
+ - * / % ( 加法,减法,乘法,除法(商),取模(取余) )
还要注意:
除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数% 操作符的两个操作数必须为整数,返回的是整除之后的余数
移位操作符
>> 右移操作符 ;
整数二进制有三种表示形式 --- 原码 , 反码 , 补码
存储到内存中的是 补码
正数三码相同
负数 -1 --- 原码 : 10000000 00000000 00000000 00000001
反码: 11111111 11111111 11111111 11111110 (符号位不变,其他位按位取反)
补码: 11111111 11111111 11111111 11111111 (反码加1)
右移操作符
移位规则:
- 算术右移 --- 右边丢弃 , 左补原符号(正0负1)
- 逻辑右移 --- 右边丢弃 , 左边补0
左移操作符
移位规则: 左边抛弃、右边补0。
注意:对于移位运算符,不要移动负数位,这个是标准未定义的
int num=10;
num>>-1; //error
位操作符
& 按位与
| 按位或
^ 按位异或(相同为0,不同为1)
练习 1: 不创建临时变量完成a,b的互换
练习 2: 求一个整数储存在内存中的二进制中的1的个数
赋值操作符
=
复合赋值符:
+= ---> a+=1 <---> a=a+1
*=
/=
%=
>>=
<<=
& =
| =
^ =
单目操作符
- ! 逻辑反操作
- -/+ 负值/正值
- & 取地址
- sizeof 操作数的类型长度(以字节为单位) --- ()中的表达式不会真实执行; 传地址(指针变量)占4个字节
- ~ 对一个二进制取反
- --/++ 前置(先--/++,再使用),后置(先使用,再--/++)
- * 间接访问操作符(解引用操作符)
- (类型) 强制类型转换
关系操作符
- >
- >=
- <
- <=
- != 用于测试 ' 不相等 '
- == 用于测试 ' 相等 '
逻辑操作符
- && 逻辑 与(全真为真)
- | | 逻辑 或(一真为真)
条件操作符(三目操作符)
exp1 ? exp2 : exp3 (解释: 1如果真,执行2 ; 1如果假,执行3 )
逗号表达式
exp1, exp2, exp3, …….expN
逗号表达式:就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。
下标引用,函数调用 和 结构成员
下标引用操作符 [ ]
函数调用操作符 ( )
接收一个或者多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
访问一个结构的成员 . ->
结构体. 成员名
结构体指针->成员名
思考:如何创建结构体类型和结构体类型变量呢?
表达式求值
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
隐式类型转换(悄悄的进行类型转换)
整型提升
- C的整型算术运算总是至少以缺省整型类型的精度来进行的。
- 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
- 是不是看的不太懂?这里我们举例说明:
算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
(比如说int类型跟float类型参与运算,先要将int转换为float类型,然后float类型与float类型运算)
操作符的属性
复杂表达式的求值有三个影响的因素。
- 操作符的优先级
- 操作符的结合性
- 是否控制求值顺序。
两个相邻的操作符先执行哪个 ? 取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。
常见问题解答:
1、如何记住运算符的15种优先级和结合性?
C语言中运算符种类比较繁多,优先级有15种,结合性有两种。
2、如何记忆两种结合性和15种优先级?下面讲述一种记忆方法。
结合性有两种,一种是自左至右,另一种是自右至左,大部分运算符的结合性是自左至右,只有单目运算符、三目运算符的赋值运算符的结合性自右至左。
优先级有15种。
记忆方法:
记住一个最高的:构造类型的元素或成员以及小括号。
记住一个最低的:逗号运算符。
剩余的是一、二、三、赋值。
意思是单目、双目、三目和赋值运算符。 在诸多运算符中,又分为:
算术、关系、逻辑。
两种位操作运算符中,移位运算符在算术运算符后边,逻辑位运算符在逻辑运算符的前面。再细分如下: 算术运算符分 * , / , % 高于 + , - 。 关系运算符中,〉,〉 = , < , <= 高于 == ,! = 。
逻辑运算符中,除了逻辑求反(!)是单目外,逻辑与( && )高于逻辑或( || )。 逻辑位运算符中,除了逻辑按位求反(~)外,按位与(&)高于按位半加(^),高于按位或( | )。
这样就将15种优先级都记住了,再将记忆方法总结如下: 去掉一个最高的,去掉一个最低的,剩下的是一、二、三、赋值。双目运算符中,顺序为算术、关系和逻辑,移位和逻辑位插入其中。
问题表达式
下面我们来看一些问题表达式:
//表达式的求值部分由操作符的优先级决定。
表达式1
a * b + c * d + e * f ;
注释∶代码1在计算的时候,由于 * 比 + 的优先级高,只能保证,* 的计算是比 + 早,但是优先级并不能决定第三个 * 比第一个 + 早执行。所以表达式的计算机顺序就可能是︰
a * b
c * d
a * b + c * d
e * f
a * b + c * d + e * f
或者 :a * b
c * d
e * f
a * b + c * d
a * b + c * d + e * f
表达式2
c + --c;
注释︰同上,操作符的优先级只能决定自减–的运算在 + 的运算的前面,但是我们并没有办法得知, + 操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。