收藏 分享(赏)

第2章 数据类型、运算符与表达式.ppt

上传人:gsy285395 文档编号:4841635 上传时间:2019-01-16 格式:PPT 页数:77 大小:297KB
下载 相关 举报
第2章 数据类型、运算符与表达式.ppt_第1页
第1页 / 共77页
第2章 数据类型、运算符与表达式.ppt_第2页
第2页 / 共77页
第2章 数据类型、运算符与表达式.ppt_第3页
第3页 / 共77页
第2章 数据类型、运算符与表达式.ppt_第4页
第4页 / 共77页
第2章 数据类型、运算符与表达式.ppt_第5页
第5页 / 共77页
点击查看更多>>
资源描述

1、第2章 数据类型、运算符与表达式,本 章 导 读数据是程序中必不可少的重要组成部分,C+语言提供了丰富的数据类型,以便能准确地描述现实世界中的各种问题。为了能方便有效地对数据进行加工处理,C+语言提供了相当丰富的运算符和表达式。本章我们主要介绍C+语言的基本元素、数据和数据类型、运算符和表达式。 本章教学目标: 了解和认识C+语言的基本字符、标识符和关键字; 理解和掌握C+语言的数据和数据类型; 理解和掌握C+语言的运算符和表达式。,第2章 数据类型、运算符与表达式,2.1 基本字符、标识符和关键字 2.2 数据与数据类型 2.3 运算符与表达式,2.1 基本字符、标识符和关键字,2.1.1

2、基本字符一个C+程序也可以看成是由C+语言的基本字符按一定的规则组成的一个序列。C+语言中使用的基本字符包括: 数字字符:09; 大小写拉丁字母:az,AZ; 其他可打印(可显示)字符: ! # % & * - + = 等; 空白字符:空格符、换行符、制表符等。,2.1.2 标识符,C+语言中用来标识函数、变量、符号常量、数组、类型、语句标号、文件等的有效字符序列称为标识符(identifier),通俗地讲,标识符就是一个名字。 在C+语言中,标识符的命名有如下限制: (1)必须以字母或下划线开头; (2)必须由字母,数字或下划线组成; (3)大小写字母是有区别的,即a和A,ABC、Abc、A

3、bC和abc是互不相同的标识符; (4)不要用C+的关键字(或称保留字,见下面)作为自定义的标识符。 (5)不要用系统中的库函数名、预处理命令等作为自定义的标识符。,下面是一些合法的标识符的例子:sum Total day _f2048 file_name a3b06 而下面的标识符则不合法:99new a-b W.S.Piter $88 cd#ab vbase 另外要注意的是: (1) ANSI C+标准都没有限定标识符的长度(字符个数),但各个C+编译系统都有自己的规定; (2) 定义标识符时应做到“见名知意”,以增加程序的可读性。 (3) 通常变量名、函数名用小写,而符号常量用大写。 (

4、4) 尽可能避免使用易混淆的字符,如:0(数字) O(大写字母) o(小写字母)1(数字) l(小写字母L) I(大写字母i)2(数字) z(小写字母) Z(大写字母)例如:no和n0,I1和l1等极易造成混淆和错误。,2.1.3 关键字(保留字),在C+语言中,已经预先定义了一些标识符,这些由系统预先定义的标识符称“关键字”,它们都有特殊的含意,不能用于其他目的。C+语言的关键字有63个,其中包括C语言关键字32个(排在前面):,在这里有二点需要指出:,一是有些关键字在低版本的C+编译系统中尚未定义(如bool、false、true 等在Borland C+ 3.1中没有定义);二是有些C+

5、编译系统扩充了很多自己定义的关键字。关于关键字我们不准备做更多的解释,随着学习的进展,读者会逐步认识它们。,2.2 数据与数据类型,C+语言中,程序所能处理的数据被分成若干种类型。数据类型不同,它所占用的存储空间、所能表示的数据范围、精度、以及所能进行的运算均不相同。C+语言的数据类型十分丰富,可分成四大类共九种,如图2.1 所示:,其中整型、字符型又有“有符号”和“无符号”之分。,2.2.1 常量和变量,在程序运行过程中,其值不能被改变的量称为常量,其值可以改变的量称为变量。 1.常量 常量按其值可分为整型常量、实型常量和字符型常量等。 另外,常量从其表现形式上又可分为直接常量和符号常量。

6、所谓直接常量是指其“值”可以从字面上直接看出来的量,因此直接常量又称为字面量(literal),如: 1, 200,3500 整型常量 835.6, 77.2, 0.618 实型常量 a, A, $ 字符型常量 符号常量是指用标识符代表的常量,应先定义后使用。,符号常量的定义有两种方式,一种方式是使用define预处理命令(详见2.7),称为宏定义,方式如下: define PI 3.1415926 define WEIGHT 85另一种方式是用const关键字来定义,如: const long int PI = 3.1415926; const int WEIGHT = 85; 使用符号常量

7、的好处是: (1)符号常量含义清楚,便于程序阅读和理解 (2)符号常量修改容易,便于程序的维护,2.变量,变量是其值在程序运行过程中可以改变的量。 变量在内存中占据一定的存储单元。 变量具有 “名”、“型”、“值”、“存储属性” 四个方面的特征。,2.2.2 基本类型,基本类型又称为“简单类型”,分为整型、字符型、实型和枚举型四种。 1.整型C+语言中的整型又分为基本整型、短整型和长整型,见表2.1:,表中的方括弧表示其中的内容是可选的,即可有可无,对使用没有影响。,说明:,字符型数据也可以作为整型数据来使用。 整型数据可进行加、减、乘、除、取模(求余数)等算术运算以及关系运算、逻辑运算和位运

8、算等。 (1)整型常量的表示方法 在C+程序中,整型常量(或称整常数)可以用十进制数、八进制数、十六进制三种形式书写。 l C+语言规定,程序中凡以数字0开头的数字序列,均作为八进制数处理; l 凡以0x或OX开头的数字序列,均作为十六进制数处理; l 其它情况下的数字序列则都作为十进制数处理。,例如,下面是合法的整型常量:3721,-7749, 0 十进制整数 03723 八进制整数 -0537 八进制整数 0x246 十六进制整数 -0X52 十六进制整数 0xADF 十六进制整数,例2.1 以十进制形式输出八进制整数和十六进制整数。 #include void main( ) print

9、f(“n%d %d %d %d %d“,03723,-0537,0x246,-0x52,0XADF); 运行结果为: 2003 -351 582 -82 2783,注意:, 书写八进制数时,只需07八个数字,因此,若写出下面的数字则是错误的:0812,0945,0879 书写十六进制数时,应有015十六个数字:09,af或AF 长整数在书写时应在整数后加字母L或l(小写L),如:135079L (十进制长整数)0200107L (八进制长整数,等于十进制65607)0Xcdefl (十六进制长整数,等于十进制数52719),例2.2 输出长整数的值 #include void main( )

10、printf(“n%ld %ld %ld %ld“,034L,0200107L,0x15L,0Xcdefl); 运行结果为: 28 65607 21 52719,(2)整型变量的定义,C+规定在程序中所有用到的变量都必须在程序中定义,即“强制类型定义”,例如: unsigned short c,d; /*定义无符号短整型变量*/ long e,f; /*定义长整型变量*/ int a=0,b=100; /*定义整型变量并赋给初值*/,例2.3整型变量的定义。 #include main( ) int a=2525, b=03721, c=0xADF; /*定义整型变量并赋初值*/long d,

11、 e, f=0Xcdefl; /*定义长整型变量并给f赋初值*/unsigned g=65535; /*定义无符号整型变量并赋初值*/d=135079L; /*给变量d赋十进制长整数值*/e=0200107L; /*给变量e赋八进制长整数值*/printf(“n%d %d %d“, a, b, c); /*输出整型变量的值*/printf(“n%ld %ld %ld”, d, e, f); /*输出长整型变量的值*/printf(“n%u“, g); /*输出无符号整型变量的值*/ 运行结果如下: 2525 2001 2783 135079 65607 52719 65535,2.实型,实型又

12、称为浮点型,分为单精度、双精度和长双精度三种,如表2.2所示:,(1)实型常量(即实数)的表示方法,实数的书写形式有两种,即十进制小数形式和指数形式,如: 3.1416,89.79,0. 十进制小数形式 1.5e-5或1.5E-5 指数形式,代表1.510-5实型数据不能进行取模(求余数)、位运算等。,(2)实型变量的定义,实型变量的定义如下所示:/定义单精度实型变量a、b、c,并给c赋初值0.0 float a, b, c=0.0; /定义双精度实型变量x、y,并分别赋初值1.2和3.610-6 double x=1.2, y=3.6e-6;,3.字符类型,在C+语言中,字符类型的数据在内存

13、中以相应的ASCII代码存放,例如,a的ASCII码为97,A的ASCII码为65,因此,a和 A 在内存中的存储分别为整数97和65。 字符型数据还可以像整型量那样参加算术运算、取模(求余数)运算、关系运算、逻辑运算以及位运算等,系统用字符的ASCII码值参加运算。 字符类型也有“有符号”和“无符号”之分。 字符类型的类型标识符、存储长度和取值范围如下表2.3所示:,(1)字符型常量,字符型常量是用一对单引号括起来的一个字符,如a,A,?,#。不能用双引号代替单引号,如”a”不是字符常量。,(2)字符型变量,字符型变量的定义和使用见下面的例子:例2.4 定义字符变量,输出字符型数据的ASCI

14、I码值。main( )char ch; /定义一个字符型变量chchA;printf(“c - %d”, ch, ch);运行结果为:A - 65,例2.5 字符型数据与整数的混合运算和输出。main( )char ch; int i; /定义字符型变量ch和整型变量ich=A;ch=ch + 32; /65+32=97,即A转变成ai=ch+1; /将字符型变量ch的值97加1后赋给整型变量iprintf(“d is cn”, ch, ch);printf(“c is dn”,i,i);运行结果如下:97 is ab is 98,(3)转义字符,“转义字符” 是指由反斜杠开头后面跟一个字母或

15、若干个数字所表示的字符。 一些特殊的“控制字符” ,只能采用转义字符用来表示,如: “回车”表示成r “换行”表示成nC+语言中的“转义字符”见表2.4。,(4)字符串常量,字符串常量是一对双引号括起来的字符序列,如:“How do you do.”, “CHINA”, “a”, “$123.45”对于字符串常量,系统自动在其结尾处附加一个“字符串结束标志”(0),以便在处理字符串时判断字符串是否结束。因此,字符串“CHINA”在内存中的实际情况是:,它的长度不是5个字符,而是6个字符,最后一个字符为0。,可以输出一个字符串,如: printf(“How do you do.”); 注意,在写

16、字符串时不必写0,否则就是画蛇添足。0字符是系统自动加上的。另外,不要将字符常量a与字符串常量“a”相混淆,二者是不同的。a和“a”的区别在于:字符常量a只占1个字节,而字符串常量“a”包含2个字符:a和0,它的长度为2个字节:,2.2.3 数据类型转换,C+中数据类型转换有两种方式,一是由程序员指定的转换,称为“强制类型转换” (或称“显式类型转换”),另一种是在进行不同类型数据的混合运算时由系统自动完成的数据类型转换(称为“自动类型转换”)。 一、强制类型转换(显式类型转换) C+提供了两种强制类型转换(或称显式类型转换)方式,可将一种类型的数据强制转换为另一种类型的数据。其中一种强制类型

17、转换方式为:(类型标识符) 表达式,下面是几个强制类型转换的例子:(char) (673.14*x) /转换为字符型数据(int)(int) x +(float) ij) /转换为整型数据f =(float) (x99); /转换为单精度实型数据,在使用强制类型转换时,应注意以下两点:,强制类型转换方式(int)的作用范围是最靠近它的表达式。对一个变量进行显式类型转换后,得到一个新类型的数据,但原来变量的类型和值都不会改变。另外一种强制类型转换方式将在第8章中介绍。,二、自动类型转换,一个合法的、多种类型数据的混合运算中,系统根据一定的原则自动进行类型转换,如图2.2所示。,下面用一个实际例子

18、来说明:,假设已指定i为整型变量,f为 float变量,d为 double型变量,e为long型,则下面式子:10 a i * f - de 的运算次序和数据类型之间的转换为(由系统自动进行): 进行 10a的运算,先将a转换成整数 97,运算结果为 107; 进行i*f的运算。先将i与f都转成double型,运算结果为double型; 整数107与i*f的积相加。先将整数107转换成double型(小数点后加若干个0,即107.00000),结果为double型; 将变量e化成 double型,de结果为 double型; 将 10ai*f的结果与de的商相减,最终结果为double型。,例

19、2.6 整型量和实型量混合运算。 #include void main() char a=8; int b=5, c=6;float e=3.5, f=3.0;printf(“n%f“, e + a % b - f/c ); 运算结果为: 6.000000,要特别说明的是:当参与运算的数是整型和字符型时,除法运算的结果是整型而不是实型,这一点一定要注意,例如: 例2.7 整型量(含字符型)的运算8/5 结果值是1,而不是1.63/5 结果值是0,而不是0.6这和数学上的计算结果不同,一定注意。,再比如,已知三角形的两边a和b及夹角c,求三角形的面积,公式为1/2absin(c),在程序中若写成

20、下式:1/2 * a * b * sin(c) 则运算结果永远为零,因为“1/2=0”。 这样的错误,计算机不会发现,编程者应特别注意。 如果要得到实数商,则应采用强制类型转换,或将参与除法运算的整数写成实数的形式,即:(float)1 / 2 * a * b * sin(c) 强制类型转换1.0 / 2 * a * b * sin(c) 将整数1写成实数的形式1.0,2.3 运算符与表达式,表达式(expression)是用运算符和括号将运算对象(也称操作数)连接起来的、符合C+语法规则的式子。 凡是表达式都有一个值(除返回空值的函数调用外),即运算结果。 运算对象包括常量、变量、函数等。

21、例如:5, x, a*bc-3.5a, tsin(a)PI*r*r, a=b=c=5, 5+(x=6)*7 等都是合法的表达式。,C+的运算符分为以下15类:,算术运算符 + - * / + - 关系运算符 = | 赋值运算符: = += -= *= /= %= = 下标运算符: 作用域算符: : 对象成员指向运算符: .* -* 其它运算符: 如函数调用运算符(),在学习运算符时应注意以下几点:,1. 运算符的功能。如加、减、乘、除等。 2. 与运算量的关系。即:(1)要求运算量的个数。一元(或单目)运算符,如负号运算符-、地址运算符;二元(或双目)运算符,如+、-、*、/ 等;三元(或三目

22、)运算符,如条件运算符“?:” 。(2)要求运算量的类型。 如 +、-、*、的运算对象可以是整型或实型数据; 而取模(求余数)运算符 % 要求参加运算的两个运算量都必须为整型数据。,3. 运算符的优先级别。 如果一个运算量的两侧有不同的运算符,应先执行“优先级别”高的运算。 4. 结合性。 如果在一个运算量的两侧有两个相同优先级别的运算符,则按结合方向顺序处理。 左结合性:“先左后右”; 右结合性:“先右后左”; 5. 结果的类型,即表达式值的类型。 尤其当两个不同类型数据进行运算时,特别要注意结果值的类型。附录C列出了所有运算符的优先级和结合性。,2.3.1 赋值运算符,1.基本赋值运算符为

23、:= 其表达式的一般形式为: 变量 = 表达式,2.复合赋值运算符 复合赋值运算符由一个数值型运算符和基本赋值运算符组合而成,共有十个:+=、 -=、 *=、 /=、 %=、 =、 &=、 =、 |=例如: a += 5 等价于 a = a + 5 x *= 6 等价于 x = x * 6 z =7 等价于 z = z 7,3.左值和右值 左值(left value,简记为l-value)或称左值表达式(l-value expressions)是能指定内存位置的表达式,因此它能出现在赋值表达式的左边。 通常一个变量是一个左值,而常量则不是左值。int a = 8; /a是变量,所以a是左值co

24、nst int b = 10; /b是常量,所以b不是左值。,右值(right value,简记为r-value)或称右值表达式(r-value expressions)是用来区别于左值的,凡不是左值或空值(void)的表达式称为右值,右值只能出现在赋值表达式的右边。 所有左值可以作为右值,但右值不能作为左值。int a; a = a + 8; /a既是左值,又是右值,8只能作右值。 一个表达式可以是左值、右值或空值(void),如:int a;(a=7)=66; /正确,a=7是左值表达式,可以再被赋值66void fun() ; /fun()被定义为不返回任何值fun(); /函数调用fu

25、n()是一个空值表达式,例2.8 赋值运算符的求值过程 (1)若a = 3,则:a = a * 5 % 2= 15 % 2=1 (2)a = 5 + (b = 2) % 4= 5 + 2 % 4= 5 + 2= 7,赋值运算符的结合性是“从右向左”的: (3)a = b = c = 5 等价于:a = (b =(c =5) 等价于:a = 5(4)若a = 3,则:a += a -= a * 5 等价于:a = a + (a -= a * 5) 等价于:a = a + (a = a - (a * 5) 等价于:a = -24,2.3.2 算术运算符,算术运算符及其优先规则是:,自下而上,优先级

26、由低到高。在同一行的运算符,是同级运算符,执行时的结合性为从左到右。,取模运算符“”为二元运算符,它用来计算两个整数相除的余数,例如: 10 7 3 5 7 5 注意:取模(求余数)运算只能用于整数,不能用于浮点数。,例2.9 算术运算符的优先级和表达式求值过程。(1) 10 + 3 * 4 / 5 -a = 10 + 12 / 5 - 97= 10 + 2 - 97= 12 - 97= - 85 (2) 10 +(int)3.6 % 3 = 10 + 3 % 3= 10 + 0= 10,(3) 2.5 + 7 % 3 * (int)(2.5 + 4.7) % 2 / 4 = 2.5 + 1

27、* (int)7.2 % 2 / 4= 2.5 + 1 * 7 % 2 / 4= 2.5 + 7 % 2 / 4= 2.5 + 1 / 4= 2.5 + 0= 2.5,2.3.3 自增(减)运算符,自增(减)运算使变量自身的值增(减)1,如: +a; /前缀式,等价于 aa1 a+; /后缀式,等价于 aa1-b; /前缀式,等价于 bb1 b-; /后缀式,等价于 bb1,使用自增(减)运算符时有两点必须注意:,1双重作用 变量自身的值和表达式的值。 如:+a 一方面它改变变量a本身的值 另一方面,表达式“+a”本身也提供一个值,即表达式的值。C+规定,对于前缀表达式,先计算变量的值,然后将

28、变量的“新值”作为表达式的值,简言之“先计算后取值”; 对于后缀表达式,则先取变量的原值作为表达式的值,然后再计算变量的“新值”,简言之“先取值后计算”。 因此对于 +a,表达式的值等于变量的新值。 而对于 a+,表达式的值等于变量的原值。,2. 自增(减)运算符只能用于左值,而不能用于右值。 例如:5+; /常量自增,错误!+(a+); /a+不是左值,错误!+(+a); /+a是左值表达式,正确!,2.3.4 关系运算符,关系运算是指对两个运算量之间大小的比较,关系运算的结果为逻辑值(或称“布尔”值,boolean)。C+语言中提供的关系运算符及其优先规则是:,自下而上,优先级由低到高。在

29、同一行上的关系运算符是同级的,同级运算符的结合性是“左结合性”。 关系运算的优先级都低于算术类,高于赋值类。,关系表达式的一般形式为: 表达式1 关系运算符 表达式2 该表达式执行时,先计算“表达式1”和“表达式2”的值,然后进行比较,比较的结果为真时关系表达式的值为1;否则为0。 注:在低版本的C+编译系统(如Borland C+ 3.1)中没有定义“逻辑量”,而用其它值代之。 在进行判断时系统视非零值为“真”,零值为“假”; 而关系运算或逻辑运算的结果若为“真”其值为1,若为“假”其值为0,结果值是无符号整数,又可参与其后的运算。 在高版本的C+编译系统(如Visual C+ 6.0和Bo

30、rland C+ 5.0)中以关键字“bool”定义逻辑变量,以关键字“true”和“false”分别表示逻辑常量“真”和“假”。,例2.10 关系运算符的优先级和关系表达式的求值过程。 (1)3+5 = 2*4 结果值为1。 (2)3 5-3 等价于(2+3)!=(5(5-3),结果值为1。 (4)x = 54 = 3 等价于:x =( 54) = 3) 等价于:x = 0,注意:对于数学中表示“x大于等于5,小于等于20”的式子:5 x 20,如果写成下面的表达式:5 = x = 20 则是错误的。但这种错误是一种语义上的错误,而不是语法上的错误,编译器查不出来,编译时不会报告错误,但运行

31、时,不论 x 为何值(比如为3、10或60)表达式的值都是“真”,所以这种错误比较“隐蔽”,不易被发现,希望引起注意。 正确的写法应该是:5 = x & x = 20 (注:&是“逻辑与”运算符,将在后面说明),2.3.5 逻辑运算符,逻辑运算符用于对操作数进行逻辑运算,逻辑运算符及其优先规则是:,自下而上,优先级由低到高。若是同级运算,!为右结合,&和 | | 为左结合。 逻辑表达式的一般形式为: ! 逻辑量 逻辑量1 & 逻辑量2 逻辑量1 | | 逻辑量2 逻辑运算的结果是逻辑值。,例2.11 逻辑运算符的优先级和逻辑表达式求值过程。 (1) !4 结果值为0。!4 等价于!(!4)=!

32、0,结果值为1。 (2) 3&4 结果值为1。3&4&5 等价于(3&4)&5,结果值为1。 (3) 3|0 结果值为1。 (4) 3&0|2 等价于(3&0)|2,结果值为1。 (5) !4|3&2 等价于(!4)|(3&2),结果值为1。,2.3.6 条件运算符,条件运算符“? :”是一个三元运算符,其使用的一般形式为: 表达式1 ? 表达式2 : 表达式3 该表达式执行时,先分析表达式1,其值为真时,则表达式2的值为条件表达式的值;否则表达式3的值为条件表达式的值。条件运算符的优先级低于算术运算符、关系运算符和逻辑运算符,高于赋值运算符,结合性为“从右到左”。具体用法可见下面的例子: 例

33、2.12 条件运算符及其表达式的求值过程。 (1)求a和b中较大者,可写成:max = a b ? a : b,(2)已知x,求函数y:,可用y = x 1 ? 1 : (x10 ? 2 : 3) 来表示。这里,“表达式3”又是一个条件表达式,构成了条件表达式的嵌套形式。,2.3.7 逗号运算符,逗号表达式的一般形式为:表达式1,表达式2,表达式n 逗号表达式的执行规则是:从左到右,逐个表达式执行,最后一个表达式的值是该逗号表达式的值。 逗号运算符“,”的优先级最低。例2.13 求下列各逗号表达式的值。 (1)a=3 , a+1, a*a 结果值是9,注意:不是16 (2)a=b=3, 6*a

34、, b=b+a 结果值是6 (3)i=1, i+=2 ? i+1 : i+4 结果值是6,2.3.8 位运算符,“位运算”是指对存储单元的每一个二进制位所进行的运算。 “位运算”是C+语言的一大特点,这使它更接近于底层硬件,在系统软件设计中非常有用,是其他高级语言所做不到的。 C+语言提供6种位运算符: 按位取反:将操作数各位的值取反; 按位与: 两操作数对应位皆为1,则结果为1,否则结果为0;| 按位或: 两操作数对应位只要有一位为1, 则结果为1,否则为0; 按位异或:两操作数对应位相异,则结果为1,否则结果为0; 右移位: 将左操作数的各二进位右移,右移位数由右操作数给出;,说明: (1

35、)算符中除以外,其他均为二元运算符,即要求两侧各有一个运算量。 (2)运算量只能是整型或字符型的数据,不能为实型数据。 (3)前四种位运算称为按位逻辑运算,它们的功能用下面的真值表表示会更清晰:,下面给出按位逻辑运算的例子以帮助理解按位逻辑运算,为简单起见,假定操作数皆为无符号字符型(8位): 43 = 212: ) 0010 1011 431101 0100 运算结果4315 = 11:0010 1011 43) 0000 1111 150000 1011 运算结果,43 | 15 = 47:0010 1011| ) 0000 11110010 11114315 = 36:0010 1011

36、) 0000 11110010 0100,(4)注意不要将逻辑运算与按位逻辑运算相混淆 例如,如果将a&b误写为a&b,则语法上没有问题,编译时不会显示错误信息,但运行时可能产生难于察觉的错误。 当a=45,b=65时,a&b和a&b皆为“真”,没有错误; 但是,当a=45,b=66时,a&b为“真”,a&b为“假” ,出现错误,这种错误是比较难查的,使用时要注意。,(5)左移位时左端最高位会溢出丢弃,而右端最低位补0。一般地,左移n位相当于乘2n。 (6)右移位时移出右端的位被舍弃,左端移入分两种情况: 逻辑右移时左端最高位移入0; 而算术右移时,左端最高位移入的值与符号位相同。 目前主流的

37、C+编译系统对无符号数均采用逻辑右移; 而对有符号数则均采用算术右移。 例如:无符号字符型数据224,表示成二进制为1110 0000,右移4位后为0000 1110,即十进制的14; 字符型数据-32,表示成二进制也是1110 0000,但右移4位后则为1111 1110,即十进制的-2。 一般地,右移n位相当于整除2n。,2.3.9 算术、关系、逻辑、赋值混合运算,我们先归纳一下这几种运算的优先级,再举例说明它们的混合运算。,关于运算符的其它情况可参见附录C。,下面是混合运算的例子:,例2.14 算术、关系、逻辑、赋值运算符的混合使用。 (1)53 & 2 | | 83)&2) | | (

38、84)&!5 | | 2 等价于:(!(34)&(!5) | | 2 等价于:(1&0) | | 2 等价于:0 | | 2 等价于:1,(3)若y已赋值整数2000,则表达式:y % 4 = = 0 & y % 100 != 0 | | y % 400 = = 0 等价于:(y%4)= =0) & (y%100) !=0) | | (y%400)= =0) 等价于:1 & 0 | | 1 等价于:0 | | 1 等价于:1(4)若a=3, b=4, c=5, 则表达式:!(a+b)+c-1& b + c/2 等价于:(!(a+b)+c-1) & (b+(c/2) 等价于:(0+5-1)&(4

39、+2) 等价于:4&6 等价于:1,2.3.10 运算顺序与副作用,ANSI C+标准中没有规定表达式中子表达式的求值顺序,因此各编译器进行代码优化时,在不破坏操作符的优先级和结合性的前提下,对子表达式的求值顺序可能会作出不同的安排,而在子表达式的求值过程中又可能会修改某个变量的值,从而导致副作用。 首先我们看一个例子: int a = 5, b = 7, c; c = a * b + (+b); 在Borland C+中c的值为48,而在Visual C+中c的值为43。之所以如此是因为在Borland C+中先计算+b,b增值为8,再计算a * b,值为40,故最后结果为48;而在Visu

40、al C+中先计算a * b,值为35,再计算+b,值为8,所以最后结果为43。,上述所有问题的根源在自增(减)运算。 在前面我们已经谈到,自增(减)运算具有双重作用,一方面它提供表达式的值,另一方面它又修改变量本身的值。一个子表达式提供其子表达式的值是进行下一步表达式运算的必要条件,是正常的作用,除此之外其他的作用(如修改变量本身的值)不是表达式运算所必须的,因此被称为“副作用”。 这就是说自增(减)运算是具有副作用的运算,其副作用在于修改变量本身的值。 同样道理,赋值运算、函数调用都有可能修改变量的值,因此用它们作子表达式时也可能产生副作用,例如: int a, b=10; a = b * 2 + (b = 15); 在Borland C+3.1和5.0中,a的值为35,而在Vidual C+ 6.0中,a的值为45。,还可举出许多例子。 但必须说明的是:副作用并不都是有害的,有时我们就是要利用它的副作用,但有时又确实是有害的,应当注意避免。 解决有害副作用的方法是分解表达式,即将复合表达式分解为简单的表达式。如果我们将前面有副作用的表达式语句改写为下面的多个表达式语句: c = b + a * b; b+; 或者: b+; c = b + a * b; 就不会产生有害的副作用了。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 实用文档 > 统计图表

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报