r=1; r=2;
该程序执行后,变量r的值不是1,而是2。 定义多个同类型变量并要给所有变量赋值,只能逐个处理,每个赋值表达式之间用逗号分开。例如,有三个整型变量x,y,z,且初始值都是10,则可以写成如下形式:int x=10, y=10, z=10;
如果变量的类型与所赋数据的类型不一致,所赋数据将被转换成与变量相同的类型。例如:int x=10.5; 该程序执行后,变量x的值是整数10。
2.2 运算符和表达式
C语言的运算符不仅具有不同的优先级,而且还有一个特点,就是它的结合性。在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算。这种结合性是其他高级语言的运算符所没有的,因此也增加了C语言的复杂性。C语言的运算符如表2-3所示。
表2-3 运算符分类表
运算符分类 算术运算符 关系运算符 逻辑运算符 位操作运算符 功能与运算符 数值运算:加(+)、减(-)、乘(*)、除(/)、取模(%)、自增(++)、自减(--) 比较运算:大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)、不等于(!=) 逻辑运算:与(&&)、或(||)、非(!) 按二进制位进行运算:位与(&)、位或(|)、位非(~)、位异或(∧)、左移(<<)、右移(>>) 赋值运算:简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)、复合位运算赋值(&=,|=,∧=,>>=,<<=) 条件求值:(?:) 若干表达式组合成一个表达式:(,) 取内容(*)和取地址(&) 计算数据类型所占的字节数(sizeof) 括号(),下标[],成员(→,.) 赋值运算符 条件运算符 逗号运算符 指针运算符 求字节数运算符 特殊运算符 表达式是由常量、变量、函数和运算符组合起来的式子。 结合性:
一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。 例: a = b = c;
b的左右两侧都为=号,而=具有右结合性,故应该由右向左计算,即:a = (b = c); 例: if (5 == 4 == 0) {}
关系运算符具有左结合性,那么先计算 5 == 4, 结果为0, 再计算0 == 0,结果为真。 printf函数的计算是从右到左进行计算
2.2.1 算术运算符和算术表达式
(1)基本的算术运算符
①加法运算符“+”:加法运算符为双目运算符,应有两个量参与加法运算。如a+b,4+8等。具有左结合性。
16
②减法运算符“-”:减法运算符为双目运算符,但“-”也可作负值运算符,此时为单目运算,例如,-x,-5等具有左结合性。
③乘法运算符“*”:双目运算具有左结合性。
④除法运算符“/”:双目运算具有左结合性。参与运算量均为整型时,结果也为整型,舍去小数。例如,10/7 结果为1,2/5 结果为0,1/3+1/3+1/3的结果也是0。如果运算量中有一个是实型,则结果为双精度实型。
⑤取模运算符“%”:双目运算,具有左结合性。要求参与运算的量均为整型。运算的结果为两数相除后的余数。例如,5%3的值为2。
(2)算术表达式和运算符的优先级和结合性
算术表达式:用算术运算符和括号将运算对象(操作数)连接起来的、符合C语法规则的式子;单独的常量、变量、函数也是表达式。
以下是算术表达式的例子: a+b (a*2)/c (x+r)*8-(a+b)/7 ++i sin(x)+sin(y) (++i)-(j++)+(k--) 书写表达式时应注意与数学公式的区别。例如,
数学式:
x?y的C表达式为:(x+y)/(a+b),可用括号调整运算的先后顺序。 a?b?b?b2?4ac数学式:的C表达式为:(-b+sqrt(b*b-4*a*c))/(2*a)
2a运算符的优先级:C语言中,运算符的运算优先级共分为14级。1级最高,14级最低。在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符优先级相同时,则按运算符的结合性所规定的结合方向处理。
运算符的结合性:C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如:算术运算符的结合性是自左至右,即先左后右。例如:表达式x-y+z,y应先与“-”号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
(3)自增、自减运算符
自增1,自减1运算符:自增1运算符记为“++”,其功能是使变量的值自增1。自减1运算符记为“--”,其功能是使变量值自减1。
自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式:
++i --i i++ i-- i自增1后再参与其他运算 i自减1后再参与其他运算 i参与运算后,i的值再自增1 i参与运算后,i的值再自减1 例如:int j=5,k=5,m,n; m=j++; // 相当于m=j; j=j+1; 运算后j的值为6,m的值为5 n=++k; // 相当于k=k+1; m=k; 运算后k的值为6,n的值为6 【例2.4】阅读程序,分析结果加深对各种算术运算的理解。 #include
17
printf(\ printf(\ printf(\ printf(\ printf(\ printf(\}
运行结果如图2-5所示:
图2-5 例2.4运行结果
说明:
i的初值为8,第4行i加1后输出故为9;第5行减1后输出故为8;第6行输出i为8之后再加1(为9);第7行输出i为9之后再减1(为8);第8行输出-8之后再加1(i为9),第9行输出-9之后再减1(i为8)。
2.2.2 关系运算符和关系表达式
关系运算是逻辑运算中比较简单的一种。所谓“关系运算”实际上就是“比较运算”,将两个值进行比较,判断比较的结果是否符合给定的条件。在程序中经常需要比较两个量的大小关系,以决定程序下一步的工作。
(1)关系运算符及其优先级 在C语言中有以下关系运算符: < 小于 <= 小于或等于 > 大于 >= 大于或等于
== 等于 != 不等于
关系运算符都是双目运算符,其结合性均为左结合。关系运算符的优先级低于算术运算符,高于赋值运算符。在六个关系运算符中,<,<=,>,>=的优先级相同,高于==和!=;==和!=的优先级相同。
(2)关系表达式
关系表达式是指用关系运算符将两个表达式连接起来的有意义的式子。 关系表达式的一般形式为: 表达式 关系运算符 表达式
例如:c>a+b,a==b 在进行关系运算时,需要注意以下几点: 关系表达式的结果是一个逻辑值,在C语言中逻辑值“真”用“1”表示,“假”用“0”表示。若关系表达式成立,则结果为1,否则,结果为0。 关系运算符的优先级低于算术运算符,高于赋值运算符“=”。 在C语言中,符号“=”用作赋值运算符,因而用“==”表示等于关系。另外,表示大于等于、小于等于、不等于所用的表示方法也和数学公式中的不同。 【例2.5】阅读程序,分析结果加深对各种关系运算的理解。 #include 18 { int a=5,b=10,c=15,d=20; printf(\ printf(\} 运行结果如图2-6所示: 图2-6 例2.5运行结果 2.2.3 逻辑运算符和逻辑表达式 (1)逻辑运算符及其优先级 关系表达式只能描述单一条件,例如x>=0,如果需要描述x>=0同时x<10,就要借助逻辑表达式了。 C语言中提供了三种逻辑运算符: && 逻辑与运算 || 逻辑或运算 ! 逻辑非运算 逻辑与运算符“&&”和逻辑或运算符“||”均为双目运算符,具有左结合性。逻辑非运算符“!”为单目运算符,具有右结合性。逻辑运算符和其他运算符优先级的关系可表示如图2-7所示。 逻辑非(!)运算符 算术运算符 关系运算符 逻辑与(&&)运算符和逻辑或(||)运算符 赋值运算符 图2-7 运算符优先级 按照运算符的优先顺序可以得出: a>b&&c>d 等价于 (a>b)&&(c>d) !b==c||d a+b>c&&x+yc)&&((x+y) 逻辑运算的值分为“真”和“假”两种,用“1”和“0”来表示。其求值规则如下: 1)逻辑与运算&&:参与运算的两个量都为真时,结果才为真,否则为假。 例如:6>0&&7>3 由于6>0为真,7>3也为真,相与的结果也为真。 2)逻辑或运算||:参与运算的两个量只要有一个为真,结果就为真;两个量都为假时,结果为假。 例如:5>0||5>8 由于5>0为真,相或的结果也就为真。 3)逻辑非运算!:参与运算量为真时,结果为假;参与运算量为假时,结果为真。 例如:!(5>0)的结果为假。 虽然C编译在给出逻辑运算值时,以“1”代表“真”,“0”代表“假”。但反过来在判断一个量是为“真”还是为“假”时,以“0”代表“假”,以非“0”的数值作为“真”。 (3)逻辑表达式 19 逻辑表达式的一般形式为:表达式 逻辑运算符 表达式 其中的表达式可以又是逻辑表达式,从而组成了嵌套的情形。 例如:(a&&b)&&c,根据逻辑运算符的左结合性,上式也可写为:a&&b&&c。 逻辑表达式的值是式中各种逻辑运算的最后值,以“1”和“0”分别代表“真”和“假”。 2.2.4 条件运算符和条件表达式 如果在条件语句中,只执行单个的赋值语句时, 常可使用条件表达式来实现。条件运算符为“ ?和:”,它是一个三目运算符,即有三个参与运算的量。 由条件运算符组成条件表达式的一般形式为:表达式1 ? 表达式2 : 表达式3 其执行的过程是:当表达式1的值为真,则以表达式2的值作为条件表达式的值,否则以表达式3的值作为条件表达式的值。 使用条件表达式时,还应注意以下几点: (1)条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符。 (2)条件运算符?和:是一对运算符,不能分开单独使用。 (3)条件运算符的结合方向是自右至左。 例如:a>b?a:c>d?c:d应理解为a>b?a:(c>d?c:d)。这也就是条件表达式嵌套的情形,即其中的表达式3又是一个条件表达式。 【例2.6】从键盘输入一个字符,如果输入的是英文大写字母,则将它转换成小写字母后输出,否则输出原来输入的字符。 #include printf(“input ch:”); scanf(“%c”,&ch); ch=(ch>=?A? && ch<=?Z? )? ch+32:ch; printf(“%c\\n”,ch); } 运行结果如图2-8所示: 图2-8 例2.6运行结果 2.2.5 赋值运算符和赋值表达式 (1)一般赋值运算符 简单赋值运算符和表达式:简单赋值运算符记为“=”。由“=”连接的式子称为赋值表达式。其一般形式为:变量=表达式 例如,x=a+b,赋值表达式的功能是计算表达式的值再赋予左边的变量。赋值运算符具有右结合性。 20