目录
在C语言中,程序需要对数据进行大量的运算,就必须利用运算符操纵数据。用来表示各种不同运算的符号称为运算符,而表达式则由运算符和运算分量(操作数)组成的式子。
1、运算符和表达式
1.1运算符
对于C语言的运算符种类、作用、包含的运算符号,概括为下表。
运算符种类 | 作用 | 包含运算符 |
算术运算符 | 用于各类数值运算 | 加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(--) |
关系运算符 | 用于比较运算 | 大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)、不等于(!=) |
逻辑运算符 | 用于逻辑运算 | 与(&&)、或(||)、非(!) |
位操作运算符 | 参与运算的量,按二进制位进行运算 | 位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>) |
赋值运算符 | 用于赋值运算 | 简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)、复合位运算赋值(&=,|=,^=,>>=,<<=) |
条件运算符 | 用于条件求值 | (?:) |
逗号运算符 | 用于把若干个表达式组合成一个表达式 | (,) |
指针运算符 | 用于取内容和取地址 | 取内容(*)、取地址(&) |
求字节运算符 | 用于计算数据类型所占的字节数 | (sizeof) |
其他运算符 | 其他 | 括号(),下标[],成员(->,.)等 |
按运算符在表达式中的运算分量的关系(连接运算分量的个数),运算符可分为:
①单目运算符,即一元运算符,只需要一个运算分量,如:-1,!a;
②双目运算符,即二元运算符,需要两个运算分量,如:a+b,x||y;
③三目运算符,即三元运算符,需要三个运算分量,如:x>y?x:y;
注意:1、有些运算符的外观虽然相同,但其作用却不同。如:“ * ”运算符在算术表达式中表示乘法,而在指针运算符中则表示获取指针变量所指向的变量的值。2、条件运算符(?:)是C语言中唯一的三目运算符。
1.2表达式
在数学中,将“3+2”称为算式,是由3 和2两个数据通过“ + ”号相连接构成的一个式子。那么 C 中运算符和数据构成的式子,就称为表达式;表达式运算的结果就称为表达式的值。因此,2+3在C语言中称为表达式,表达式的值为 5。
根据运算符的分类,可以将 C 语言中的表达式分为 8类:算术表达式、关系表达式、逻辑表达式、赋值表达式、条件表达式、逗号表达式、位表达式和其他表达式。
由以上表达式还可以组成更复杂的表达式,例如:
z=x+(y>=0)
从整体上来看这是一个赋值表达式,但在赋值运算符的右边,是由关系表达式和算术表达式组成的。
1.3优先级与结合性
C 语言中规定了运算符的优先级和结合性。
优先级是指当不同的运算符进行混合运算时,运算顺序是根据运算符的优先级而定的,优先级高的运算符先运算,优先级低的运算符后运算。在一个表达式中,如果各个运算符有相同的优先级,运算顺序是从左向右,还是从右向左,是由运算符的结合性确定的。
所谓结合性是指运算符可以和左边的表达式结合,也可以与右边的表达式结合。比如 x+y*z,应该先做乘法运算,再做加法运算,相当于 x+(y*2),这是因为乘号的优先级高于加号。
当一个运算分量两侧的运算符优先级相同时,要按运算符的结合性所规定的结合方向处理,即左结合性(自左至右运算)和右结合性(自右至左运算)。
例如表达式x-y+2,应该先进行x-y 运算,然后再进行+z的运算,这就称为“左结合性”,即从左向右进行计算。
最典型的右结合性算术运算符,它的结合性是自右向左,如 x=y=z,由于“=”的右结合性因此应先进行 y=z运算,再进行 x=(y=z)运算。
2、算术运算符和表达式
2.1算术运算符
基本的算术运算符有5个,如下表所示:
符号 | 说明 |
+ | 加法运算符或正值运算符 |
- | 减法运算符或负值运算符 |
* | 乘法运算符 |
/ | 除法运算符 |
% | 求模运算符或求余运算符 |
以上运算符的运算分量必须是数值型的,即整型(int、char 及相关类型)和浮点型(float、double及long double)。其中,+(正值运算符)和-(负值运算符)是单目运算符,其余的均为双目运算符,即该运算符连接了两个运算分量。
2.2算术表达式
算术表达式如同数学的基本四则混合运算,举例子:
算术表达式举例 | 数学中的表示 | 含义 | 表达式的值 |
2+3 | 2+3 | 2与3相加 | 5 |
2-3 | 2-3 | 2与3相减 | -1 |
2*3 | 2×3 | 2与3相乘 | 6 |
2/3 | 2÷3 | 2与3相除 | 0 |
2%3 | 2对3求余数 | 2 |
复杂的算术表达式,例如:
2*(9/3) 结果为:6
10/((12+8)%9) 结果为:5
注意:1.“ % ”运算符要求两侧的运算分量必须为整型数据。这个很好理解,如果是有小数部分的话,就不存在余数了。例如 6.0%4 为非法表达式。对负数进行求余运算,规定若第 1个运算分量为正数,则结果为正;若第1个运算分量为负,则结果为负。2.在C语言中,乘法运算符为“ * ”,而不能写成数学中的“ x ”号;除法运算为“ / ”,而不是“ ÷ ”号。程序中的表达式必须写在一行上,如数学中的,在程序中必须写成(a+b)/(c-d);
2.3算术运算符的优先级和结合性
在复杂的算术表达式中,“ () ”的优先级最高,“ *、/、% ” 运算符的优先级高于 “ +、- ” 运算符。因此,可适当添加括号改变表达式的运算顺序,并且算术运算符中的结合性均为“ 左结合 ”,可概括如下:
(1)先计算括号内,再计算括号外;
(2)在没有括号或在同层括号内,先进行乘除运算,后进行加减运算;
(3)相同优先级运算,从依次进行;
3、关系运算符和表达式
3.1关系运算符
C 语言提供有6种关系运算符,分别是:>(大于)、>=(大于等于)、<(小于)、<=(小于等于)、==(等于)、!=( 不等于)。它们都是双目运算符。
注意:以下这些运算符不同于平时的书写习惯:(1) “ >= ” 和 “ <= ”不能写成“ ≥ ” 和 “ ≤ ”;(2)等于在C中的书写格式为 “ == ” 而不是 “ = ”,注意是两个 “ = ” 连起来写表示相等的关系,“ = ”是后面要讲的赋值运算符,应注意二者的区别;(3)不等于的书写格式为“ != ”,而不是平时书写的“ ≠ ”。
3.2关系表达式
用关系运算符把两个 C语言表达式连接起来的式子称为关系表达式。关系表达式的结果只有两个:1 和 0。关系表达式成立时值为 1,不成立时值为 0。
例如,若 x=3,y=5,z=-2,则:
x+y<z的结果不成立,表达式的值为0。
x!=(y>2)的结果成立,表达式的值为1(因为y>z的结果成立,值为1不等于1结果成立,整个表达式的值为 1)。
3.3关系运算符的优先级和结合性
在这6种关系运算符中,“ > ”、“ >= ”、“ < ” 和 “ <= ”的优先级相同,“ == ” 和 “ != ”的优先级相同,前 4 种的优先级高于后两种。
例如:
a==b<c 等价于a==(b<c)
a>b>c 等价于 (a>b)>c
关系运算符中的结合性均为“左结合”。
4、逻辑运算符和表达式
4.1逻辑运算符
逻辑运算符主要用于逻辑运算,包含“ && ”(逻辑与)、“ || ” (逻辑或)、“ !”( 逻辑非)等3种。逻辑运算符的真值表如下。
a | b | a&&b | a||b | !a |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 0 |
0 | 1 | 0 | 1 | 1 |
0 | 0 | 0 | 0 | 1 |
其中, “ ! ”是单目运算符,而“ && ”和“ || ”是双目运算符。
提示:逻辑反( ! ),其结果是运算分量逻辑值的“ 反 ”;逻辑与(&&),仅当两个运算分量同时为真时,结果才为真;否则,只要其中有一个为假,结果就为假。逻辑或( || ),只要其中有一个运算分量为真,结果就为真;仅当二者同时为假时,结果才为假。
4.2逻辑表达式
逻辑运算符把各个表达式连接起来组成一个逻辑表达式,如:a&&b、1||( !x )。逻辑表达式的值也只有两个:0 和 1。0代表结果为假,1代表结果为真。
例如,当x为0时,x<-2 && x>=5 的值为多少。
当x=0时, 0<-2 结果为假,值等于0; 0>=5 结果也为假,值为 0;0&&0,结果仍为 0;
当对一个量(可以是单一的一个常量或变量 )进行判断时,C 编译系统认为:代表“ 假非0代表“真”。例如:
若a=4,则!a 的值为0(因为a为4,非0,被认为是真,对真取反结果为假,假用0表示);a&&-5 的值为 1(因为a 为非 0,认为是真,-5 也为非 0,也是真,真与真,结果仍为真真用1表示);
4||0的值为1(因为4为真,0 为假,真假,结果为真,用1表示)。
4.3逻辑运算符的优先级和结合性
在这三种逻辑运算符中,它们的优先级别各不相同。逻辑非( ! )的优先级别最高,逻辑与( && )的优先级高于逻辑或( || )。
如果将前面介绍的算术运算符和关系运算符结合在一起使用时,逻辑非( ! )优先级最高,然后是算术运算符、关系运算符、逻辑与( && )、逻辑或( || )。
比如:5>3&&2||!8<4-2等价于 ((5>3)&&2)||((!8)<(4-2)),结果为:1。
运算符 “ ! ” 的结合性是“ 右结合 ”,而“ &&” 和“ || ”的结合性是“ 左结合 ”。
5、条件运算符和表达式
条件运算符由 “ ? ” 和 “ : ” 组成,是 C 语言中唯一的一个三目运算符,是一种功能很强的运算符。用条件运算符将运算分量连接起来的式子称为条件表达式。
条件表达式的一般构成形式是:
表达式1?表达式2:表达式3
条件表达式的执行过程是:
①先计表达式1的值;
②若该值不为 0,则计算表达式 2的值,并将表达式 2的值作为整个条件表达式的值;
③否则,就计算表达式3 的值,并将该值作为整个条件表达式的值。
例如:(x>=0)?1:-1
该表达式的值取决于 x 的值,如果 x 的值大于等于 0,该表达式的值为 1,否则表达式的值
为-1。
6、赋值运算符和表达式
赋值运算符是用来给变量赋值的。它是双目运算符,用来将一个表达式的值送给一个变量。
6.1赋值运算符
在C语言中,赋值运算符有一个基本的运算符( = )。
C 语言中允许在赋值运算符“ = ”的前面加上一些其他的运算符,构成复合的赋值运算符。
复合赋值运算符共有 10 种,分别为:+=、-=、*= 、/=、%=、<<=、>>=、&=、^=、!=。后五种与位运算符组合而成。C语言规定,所有的双目运算符都可以与赋值运算符一起构成复合赋值运算。
6.2赋值表达式
由赋值运算符将一个变量和一个表达式连接起来的式子称为赋值表达式。赋值表达式的一般格式为:
变量=表达式
对赋值表达式求解的过程是:将赋值运算符右侧的 “ 表达式 ” 的值赋给左侧的变量。整个赋值表达式的结果就是被赋值的变量的值。
说明:右侧的表达式可以是任何的常量、变量或表达式(只要它能生成一个值就行)。但左侧必须是一个明确的、已命名的变量,也就是说,必须有一个物理空间可以存储赋值号右侧的值。例如:
//简单的赋值表达式例子
#include<stdio.h>
int main()
{
int a=5; //a的值为5,整个表达式的值为5
int x=0;
int y=0;
x=10+y;
printf("%d %d",a,x); //这样就可以打印出a、x的值
return 0;
}
注意:不能把任何东西赋给一个常量-----常量不能放在赋值号的左边,例如:5=a;就不对。
对赋值运算符的说明如下:
(1)赋值运算符“ = ”与数学中的等式形式一样,但含义不同。“ = ”在 C 语言中作为赋值运
算符,是将“ = ”右边的值赋给左边的变量;而在数学中则表示两边相等。
(2)注意“==”与“=”的区别,例如:a==b<c 等价于 a==(b<c),作用是判断 a 与(b<c)的结果是否相等;a=b<c 等价于 a=(b<c),作用是将b<c 的值赋给变量a。
(3)赋值表达式的值等于右边表达式的值,而结果的类型则由左边变量的类型决定。比如浮点型数据赋给整型变量,截去浮点数据的小数部分;
整型数据赋给浮点型变量,值不变,但以浮点数的形式存储到变量中;字符型赋给整型,由于字符型为一个字节, 而整型为 2个字节,故将字符的 ASCII 码值放到整型量的低8位中,高8位为0;
整型赋给字符型,只把低8位赋予字符量。
注意:①复合运算符在书写时,两个运算符之间不能有空格,否则就是错误的;②复合赋值运算符右边的表达式应作为一个整体对待。
6.3赋值运算的优先级和结合性
在使用赋值表达式时有以下几点说明。
(1)赋值运算可连续进行。例如:
a=b=c=0 等价于 a=(b=(c= 0)) ,即先求c=0,c的值为 0,再把0赋给 b,b的值为0,最后再把0赋给 a,a 的值为 0,整个表达式的值也为0,因为赋值运算符是“ 右结合 ”。
(2)赋值运算符的优先级比前面介绍的几种运算符的优先级都低。例如:
a=(b=9)*(c=7) 等价于a=((b=9)*(c=7))
y=x==0?1:sin(x)/x 等价于y=(x==0?1:sin(x)/x )
max=a>b?a:b 等价于 max=(a>b?a:b)
7、自增、自减运算符
C 语言提供有两个特殊的运算符,通常在其他计算机语言中是找不到它们的:自增运算符++和自减运算符--。它们都是单目运算符,运算的结果是使变量值增 1 或减 1 。可以在变量之前称为前置运算;也可以在变量之后,称为后置运算。它们都具有“右结合性”。有以下几种形式:
++i /*相当于i=i+1,i自增后再参与其他运算*/
--i /*相当于i=i-1,i自减后再参与其他运算*/
i++ /*相当于i=i+1,i参与运算后,i的值再自增1*/
i-- /*相当于i=i-1,i参与运算后,i的值再自减1*/
注意:++、--中间不能有空格。该运算符本身带有赋值操作,因此自增自减运算符只能用于变量,不能是常量或是表达式,比如:3++、--(a+b)都是不合法的。
为了加深理解,详细说明一下 i++与++i、i--与--i:
从作用上看,i++与++i都相当于i=i+1,i--与--i相当于i=i-1。但它们之间有不同之处以i++和++i为例,i++是先使用 i 的值,再执行i=i+1,而++i是先执行i=i+1后,再使用i的值。
例如:若 i 初值为 1,则:
j=i++; /*执行后 j 的值为1,i 的值为2;因为先执行 j=i,将 i 的初值1赋给 j ,此时 j=1,然后再执行i=i+1=2;*/
j=++i; /*执行后 j 的值为 2,i 的值为2;因为先执行i=i+1=2,将 i 的值2赋给 j ,此时 j=2;*/
8、逗号运算符和表达式
在 C 中,逗号不仅作为函数参数列表的分隔符使用,也作为运算符使用。号运算符的功能是把两个表达式连接起来,使之构成一个逗号表达式。逗号运算符在所有运算符中是级别最低的。其一般形式为:
表达式1,表达式2
求解的过程是:先计算表达式 1,再计算表达式 2,最后整个逗号表达式的值就是表达式 2 的值。
9、运算符的优先级
C 语言中,运算符的优先级共分为 15 级。1 级最高,15 级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而当一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。前面已经介绍了 7种常用的运算符的书写形式和使用方法,下面列出 C 中所有运算符的优先级。
运算符类型 | 优先级 | 运算符 |
基本 | 1 | () . -> [] :: .* ->* &(引用) |
单目 | 2 | * & new delete ! ~ ++ -- sizeof + - |
算术 | 3 | * / % |
算术 | 4 | + - |
移位 | 5 | >> << |
关系 | 6 | < <= > >= |
关系 | 7 | == != |
位逻辑 | 8 | & |
位逻辑 | 9 | ^ |
位逻辑 | 10 | | |
逻辑 | 11 | && |
逻辑 | 12 | || |
条件 | 13 | ?: |
赋值 | 14 | = += -= *= /= %= |= ^= &= >>== <<= |
逗号 | 15 | , |
(1)当一个表达式包含两个或两个以上的运算符时,运算分量的结合方式由优先级决定。先计优先级高的,再计算优先级低的。
例如:
5 +3*2,因为乘法运算符的优先级比加法运算符高,所以 3和2相乘,得到6,然后6和5相加,得到11。
(2)如果一个表达式包含的运算符优先级相同,则按照结合性规定的方向处理。
例如:
a/b%c,因为/和%具有相同的优先级,按左结合的结合性,等价于:(a/b)%c。!p++,因为!和++优先级相同,而且都是右结合,因此等价于:!(p++)
(3)通常可以使用圆括号强制地把运算分量结合在一起。被括号括住的子表达式会被当做一个独立的个体进行处理,这个个体同样要受到优先级和结合性的约束。
例如:
(5 +3*2)%7
这里强制把 5+3*2 当成一个个体来处理。因为乘法运算符的优先级比加法运算符高,所以3*2=6;然后5和6相加,得到11;11对7取余得到4。
由于赋值运算符的结合性是从右到左,所以:i=j=k=1 的结合方式等价于:(i=(j=(k = 1)))。
注意: 当一个表达式中出现多个有不同优先级的运算符时,可以通过加圆括号的方式改变运算的顺序。