运算符与表达式
运算符的分类
根据不同的分类标准,我们可以将运算符分为两类。
第一类是按照操作对象的多少进行划分的。我们有下面的表格:
| 一元运算符 | 二元运算符 | 三元运算符 |
|---|---|---|
| +-正负号 | +-加,减*/%乘,除,取余 | ?:条件运算 |
| ++自加 | <<>>左移,右移 | |
| --自减 | &&||!与或非运算,^异或运算 | |
| !非 | <>大于,小于 | |
| ~按位取反 | >=<=!=大于/小于等于,不等于 | |
| *指针运算符 | =,&,|赋值按位,与,或 | |
| 第二类是按照功能划分。我们可以分为以下内容 | ||
| 算术运算符 | 赋值运算符 | 逻辑运算符 |
| -- | -- | -- |
| +-加减 | =赋值 | &&与 |
| */乘除 | +=/-=加等减等 | ||或 |
| %取余 | *=//=乘等除等 | !非 |
| ++自增 | %=取余等 | ==等于 |
| --自减 | &=,|=,^=,>>=,<<=位运算等 | <<左移 |
表达式的分类
根据运算符,我们可以把表达式分为以下几类:
1、算术表达式
算术表达式由算术运算符和控制运算优先级的括号组成,是进行算术运算的基本表达形式。
(l+o+v+e)*521/1314.0;
3.1415926*r;
2、赋值运算符
赋值运算符由赋值运算符,算术运算符和操作对象复合而成,最后以'='连接.
变量=表达式或者数值//在定义时或者定义完成后初始化都可以
eg:love=5211314;
变量一=变量二=变量三=变量N=表达式或者值//只能在定义后初始化使用
eg:l=o=v=e=1314;
3、逻辑表达式
一般由逻辑运算符和操作对象组合而成,属于C语言中进行逻辑判断的主要表达形式,也是条件控制语句中的常用的表达式。
a&&b
c||d&&m
!x
4、关系表达式
关系表达式一般由关系运算符和操作对象组成,关系运算符也常用与条件控制语句复合使用。
eg:love>1314
m==n//注意:等于判断有两个等号
5、逗号表达式
逗号表达式有其他运算符和逗号组成,常用于变量定义和for循环中.
int a,b,c;
c=(a=3,b=5,a=a+b);
值得注意的是,逗号表达式的值总是等于最后一个表达式的值。
6、复合表达式
由其他表达式组成的表达式。
love=521+b+(c=35/(d=7));
运算符的优先级与结合性
| 优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
|---|---|---|---|---|---|
| 1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | |
| () | 圆括号 | (表达式)/函数名(形参表) | |||
| . | 成员选择(对象) | 对象.成员名 | |||
| -> | 成员选择(指针) | 对象指针->成员名 | |||
| ++ | 后置自增运算符 | ++变量名 | 单目运算符 | ||
| -- | 后置自减运算符 | --变量名 | 单目运算符 | ||
| 2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
| (类型) | 强制类型转换 | (数据类型)表达式 | |||
| ++ | 前置自增运算符 | 变量名++ | 单目运算符 | ||
| -- | 前置自减运算符 | 变量名-- | 单目运算符 | ||
| * | 取值运算符 | *指针变量 | 单目运算符 | ||
| & | 取地址运算符 | &变量名 | 单目运算符 | ||
| ! | 逻辑非运算符 | !表达式 | 单目运算符 | ||
| ~ | 按位取反运算符 | ~表达式 | 单目运算符 | ||
| sizeof | 长度运算符 | sizeof(表达式) | |||
| 3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
| * | 乘 | 表达式*表达式 | 双目运算符 | ||
| % | 余数(取模) | 整型表达式/整型表达式 | 双目运算符 | ||
| 4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
| - | 减 | 表达式-表达式 | 双目运算符 | ||
| 5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
| >> | 右移 | 变量>>表达式 | 双目运算符 | ||
| 6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
| >= | 大于等于 | 表达式>=表达式 | 双目运算符 | ||
| < | 小于 | 表达式<表达式 | 双目运算符 | ||
| <= | 小于等于 | 表达式<=表达式 | 双目运算符 | ||
| 7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
| != | 不等于 | 表达式!= 表达式 | 双目运算符 | ||
| 8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
| 9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
| 10 | |按位或 | 表达式 | 表达式 | 左到右 | 双目运算符 |
| 11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
| 12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
| 13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
| 14 | = | 赋值运算符 | 变量=表达式 | 右到左 | |
| /= | 除后赋值 | 变量/=表达式 | |||
| *= | 乘后赋值 | 变量*=表达式 | |||
| %= | 取模后赋值 | 变量%=表达式 | |||
| += | 加后赋值 | 变量+=表达式 | |||
| -= | 减后赋值 | 变量-=表达式 | |||
| <<= | 左移后赋值 | 变量<<=表达式 | |||
| >>= | 右移后赋值 | 变量>>=表达式 | |||
| &= | 按位与后赋值 | 变量&=表达式 | |||
| ^= | 按位异或后赋值 | 变量^=表达式 | |||
| |= | 按位或后赋值 | 变量|=表达式 | |||
| 15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | 从左向右顺序运算 |
我们简单总结一下常用运算符优先级的记忆方法:
括号前置自增减>非指针后置自增减>算术运算>关系运算(不等关系>等关系[==,!=])>逻辑运算>赋值运算>逗号运算
除了第二级别为右结合,其余为左结合(注意区别没有运算结合性的问题).
运算符详解
1、赋值运算符
赋值运算符为:‘=’,我们要注意区别‘=’和‘==’的区别,前一个是赋值运算符属于赋值运算,后一个属于关系运算的等关系判断。‘=’并不是等于,而是赋值。
由于‘=’为二元运算符,所以至少需要两个操作数,对于‘=’左侧,我们称之为左值(l-value),并且约定左值必须是变量,常量和表达式不能作为左值.
eg:a+1=2是错误的,
5=a;也是错误的.
‘=’右侧为右值,对右值的要求没有左值这么高,他可以是常量,变量,甚至是表达式。
为保证赋值没有出现隐形错误,我们需要保证,赋值运算满足以下两个条件,左右类型相同或者,左精度高于右精度。
对于复合赋值运算符,我们可以通过这一个公式进行相应的转化:
a(fun)=c;=>a=a(fun)c;
不过为了保证程序的可读性与可移植性,一般情况下,我们不采用复合复制的做法,
2、算术运算符
这一个运算符,我们分为两部分,第一部分使我们所熟知的+,-,*这三个运算和我们在现实生活中的运算相差无几,另外,我们把/,%单独拿出来阐述.
我们举一个栗子来说明一下这三个运算符:
int a=2,b=3,c=5;
float f=2.1;
printf("%d,%d,%d",a+b,b-a,a*b);
printf("%f,%f,%f",a*f,b*f,c&f);
输出结果请大家自己尝试.
对于'/'与我们现实中唯一的我差别就是数据类型不同造成的误差,例如:3/2,不难算出,答案为1.5,但是计算机处理的时候,输出结果为1.这就是原因所在。
造成这个问题的原因就在于两个int整型相除,得到的结果仍然为整型,造成了小数部位的舍弃,为了避免这种问题,我们一定要看清楚我们的运算是否类型一致.
当然处理这个问题,我们还有一个方法,就是强制类型转换。例如:3.0/2的结果就为1.5,(float)3/2的结果也为1.5.
对于'%'运算,我们并不陌生,但是对于这个运算符,我们需要注意这些地方:
1)'%'不能对实型进行运算,也就是浮点型(float、double)。
2)'%'的实质为:(假设原数为n,取余的操作数为c)则n%c=n-floor(n/c)*c;
其中floor为向下去整.
3)%两边为正整数,那么结果为正整数或者0;
%两边为负整数,那么结果为负整数或者0;
%左侧为正整数,那么结果为正整数或者0;
%左侧为负整数,那么结果为负整数或者0;
3、++,--运算符
我们分为两类,三个板块,分别问前缀和后缀以及二者的对比及运算的影响。
前缀:++a、--b特点是先运算在使用。
例如:
int a=5;
printf("%d",++a);
//结果为6
容易想到,--运算符也是如此。
后缀:a++,b--的特点是先使用后自增
例如:
int a=5;
printf("%d",a++);
//结果为5;
对比:
| 项目 | 前缀 | 后缀 |
|---|---|---|
| 优先级 | 高 | 低 |
| 操作对象 | 合法的左值 | 合法的左值 |
| 结合性 | 左结合 | 右结合 |
4、关系运算符和关系表达式
1)运算结果为bool值,即0/1
2)结合性为自左向右
3)优先级:不等相关关系大于等相关关系.
int a=3,b=4,c=5,d;
d=b>a>c;
printf("%d",d);
请读者思考这个问题的答案结果是多少,这也是在考试中经常设置的一个坑。
5、逻辑运算符
1)逻辑与&&,特点:二者全为真,则表达式为真。
2)逻辑或||,特点:二者全为假,则表达式为假、
3)逻辑非!,特点,真假呼唤,真变假,假变真.
注意,逻辑运算具有短路特性,只有前面一个无法确认整个表达式的值时,才会判断下一个。
例如:与如果前为假。那么根据定义,表达式的值必定为假,所以后面的表达式就不需要计算了,同样或也具有短路特性,如果前面为真,那么就不会判断后面的表达式的值。
int a=0,b=0,c=0;
c=++a||b++;
printf("%d,%d,%d",a,b,c);
请大家完成这一个练习.
此外,我们需要记住一个经常使用的判断闰年的程序,核心代码如下:
if((year%4==0)&&(year%100!=0)||(year%400==0)return 1;
对于位运算符,我们在这里先不做深究。
不过,我们在这里给出一个交换变量的程序,供大家品鉴:
int a=2,b=3;
a=a^b;
b=b^a;
a=a^b;
/*
如果不用异或运算,我们还可以这样写:
a=a+b;
b=a-b;
a=a-b;
*/
printf("%d,%d",a,b);
Thanks!

浙公网安备 33010602011771号