第二章基本数据类型运算符和表达式_第1页
第二章基本数据类型运算符和表达式_第2页
第二章基本数据类型运算符和表达式_第3页
第二章基本数据类型运算符和表达式_第4页
第二章基本数据类型运算符和表达式_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第二章 C语言的基本数据类型、运算符和表达式21 数据类型的概念数据类型是指数据的内在表现形式。通俗地说,我们把数据在加工计算中的特征称为数据的类型。数据类型包含两方面的含义:一是该类型数据可以取值的范围;二是在该范围内的数据可以进行的操作。例如,两个人的年龄可以进行加法、减法运算;两个人的工资也可以进行加法、减法运算。年龄和工资都具有一般数值的特点,在C语言中称为数值型,其中年龄是整数,所以称为整型;工资一般为实数,所称为实型。又如两个人的姓名是不能进行加法、减法运算的,这种数据具有文字的特征,在C语言中称为字符串。单个字符称为字符型数据。在C语言中我们把整型和实型全称为“数值型”,把数值型

2、和字符合称为“基本数据类型”。此外,C语言根据数据加工处理的特征,还设有其它复杂的数据类型,具体如图2.1.1所示。短整型长整型无符号整型无符号短整型无符号长整型 整型单精度型双精度型基本类型 实型 字符型数组型结构体型联合体型构造类型数据类型 指针型枚举型空类型 图2.1.1 C语言的数据类型其中“构造类型”是指由若干个相关的基本数据类型组合在一起形成的一种复杂的数据类型。例如,若干个人的年龄组合在一起,就是一个数组,若干个人的基本工资、职务工资、奖金组合在一起,也是一个数组。前者是由整型数据组成的一维数组,后者是由实型数据组成的二维数组。又如,一个人的姓名、年龄、基本工资也可以组合在一起,

3、它们的数据类型不同,在C语言中称为“结构体类型”。如果有若干个数据不同时使用,我们也可以让它们占用相同的内存区域,以便节省内存,这些数据组合在一起就是“联合体类型”,联合体类型中的数据可以是同类型的,也可以是不同类型的。指针型是一种简单的数据类型,它是用来表示内存地址的。指针类型的数据可以表示基本类型数据的地址,也可以表示结构类型数据的首地址和其中某个具体数据的地址,还可以表示某指针的地址(称为指针的指针)。例如存放一个人年龄的内存的地址,存放某数组的首地址,存放某结构数据的首地址都可以用指针型数据来存放。设立指针型数据是为了方便C语言的动态处理。如果某数据在程序运行中,只有固定的几个值,我们

4、就可以把这几个值列出来,以后这个数据只能取确定的几个值中的某一个。这种数据在C语言中就叫做“枚举型”。空类型是从语法完整性的角度给出的一个数据类型,表示该处不需要具体的数据值,因而没有数据类型。每个数据都要在内存中(个别数据可能在寄存器中)分配若干个字节,用于存放该数据。不同类型的数据在内存中占用的字节数是不同的,因此C语言要求每使用一个数据之前,必须对数据的类型加以说明(常量不必事先说明),以便为其安排合适的内存。C语言的基本数据类型有整型、实型和字符型,各类型的分类及表示方法见表2.1.1。表2.1.1 C语言基本数据类型分类类 型表示方法占位值 域整型基本整型int16-215(215-

5、1)短整型short16-215(215-1)长整型long32-231(231-1)无符号整型unsigned160(216-1)无符号短整型unsigned short160(216-1)无符号长整型unsigned long320(232-1)实型单精度实型float323.4E-383.4E+38双精度实型double641.7E-3081.7E+308长双精度实型long double803.4E-49321.7E+4932字符型基本字符型char void8-128127无符号字符型unsigned char80255本章主要介绍基本数据类型的数据特征、说明方法和使用,其它数据类型

6、将在后续章节中逐步介绍。22 常量、变量与标识符 2.2.1 常量和符号常量在程序运行过程中,其值不能被改变的量称为常量。常量区分为不同的类型,如12、0、-3为整型常量,4.6、-1.23为实型常量,a、d等为字符常量。常量一般从其字面形式即可判别。也可以用一个标识符代表一个常量,如:例2.2.1#define PRICE 30main ( )int num, total;num=10;total=num*PRICE;printf(total=%d,total);程序中用#define命令行定义PRICE代表常量30,此后凡在此文件中出现的PRICE都代表30,可以和常量一样进行运算,程序运

7、行结果为total=300有关#define命令行的详细用法参见后续章节。这种用一个标识符代表一个常量的,称为符号常量,即标识符形式的常量。注意符号常量不同于变量,它的值在其作用域(在本例中为主函数)内不能改变,也不能再被赋值。如再用以下赋值语句给PRICE赋值:PRICE=40;是错误的。习惯上,符号常量多用大写,变量用小写,以示区别。2.2.2 变量其值可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储单元。在该存储单元中存放变量的值。请注意区分变量名和变量值这两个不同的概念。和其它高级语言一样,用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列称为

8、标识符(identifier)。简单地说,标识符就是一个名字。C语言规定标识符只能由字母、数字和下划线三种字符组成,且第一个字符必须为字母或下划线。如下面是合法的标识符,也是合法的变量名。 Sum, average, class, day, month, student, _name, lotus1_2_3, basic.下面是不合法的标识符和变量名: M.D.John, $123, x/y, #33, 3D64, ab注意,大写字母和小写字母被认为是两个不同的字符。因此,sum和SUM是两个不同的变量名。习惯上,变量名用小写字母表示,以增加可读性。C语言中标识符的长度(字符个数)无统一规定,

9、随系统而不同。许多系统(如IBM PC的MS C)取前8个字符,假如程序中出现的变量名长度大于8个字符,则只有前面8个字符有效,后面的不被识别。例如,有两上变量:student_name和student_number,由于二者的前8个字符相同,系统认为这两个变量是一回事而不加区别。可以将它们改为:stud_name和stud_num,以使之区别。因此,在写程序时应注意了解所用系统对标识符长度的规定,以免出现上面的混淆。这种错误并不反映在编译过程中(即语法无错误),但运行结果显然不对。在选择变量名和其它标识符时,应注意做到“见名知意”,即选有含意的英文单词(或其缩写)作标识符,如count, n

10、ame, day, month, class, city, country等,除了数值计算程序外,一般不要用代数符号(如a、b、c、x1、y1等)作变量名,以增加程序的可读性。这是结构化程序的一个特征。本书在一些简单的举例中,为简单起见,仍用单字符的变量名(如a、b、c等),请读者注意不要在其它所有程序中都如此。在C语言中,要求对所有用到的变量作强制定义,也就是“先定义,后使用”,如例1.2.2、例1.2.3那样。这样做的目的是:1凡未被事先定义的,不作为变量名,这就能保证程序中变量名使用的正确。例如,如果在定义部分写了 int student;而在执行语句中错写成statent。如 stat

11、ent=30;在编译时检查出statent未经定义,不作为变量名,因此输出“变量statent未经说明”的信息,便于用户发现错误,避免变量名使用时出错。 2每一个变量被指定为一确定类型,在编译时就能为其分配相应的存储单元。如指定a、b为int型,如果所用的IBM PC的Turbo C,则为a和b各分配两个字节,并按整数方式存储数据。3每一变量属于一个类型,就便于在编译时据此检查该变量所进行的运算是否合法。例如,整型变量a和b,可以进行求余运算:a%b%是“求余”(见 2.6节),得到a/b的整余数。如果将a、b指定为实型变量,则不允许进行“求余”运算,在编译时会指出有关“出错信息”。223 标

12、识符及其命名在2.2.2中我们已经说明了标识符的使用,下面我们再对其总结如下:标识符是一种特定的字符序列,用来标记:变量名、符号常量名、数组名、函数名、类型名、标号和文件名等。1、所使用的字符必须使用C符号集中的英文字母、数字和下划线。2、长度ANSI标准规定标识符长度可以是132个字符。但是,在PC机中,标识符长度只有前面8个字符有效,超过8个字符后的字符将被忽略。例如,filename1与filename2被认为是同一个标识符。3、命名规则标识符的命名,必须以英文字母或下划线开头,其后可以跟或不跟其它合乎规定的字符。C语言严格区分字母的大小写,例如:BIG、big、Big、Big等都是不同

13、的标识符。标识符本质上代表名字,因此命名要有意义。下面给出一些合法的与不合法的标识符名字。正确错误sum2aformula#abcala+ba2%xWang_MingWangMingY_M_Dtest!1 2.4 关键字关键字又叫保留字,是C编译系统预先定义的一些有特定含义的标识符。C语言将这些关键字定义成:存储类型符、数据类型符和语句定义符。它们只能按定义加以使用,而不能作常规的标识符使用。因此,在程序中选用变量名、函数名等标识符时,不能与关键字发生冲突。ANSI的C标准总共规定了32个关键字,都是用小写字母组成的,如表2.2.1所示。表2.2.1 ANSI C标准规定的32个关键字auto

14、doubleintstructbreakelselongswitchcaseenumregistertypedefcharexternreturnunionconstfloatshortunsignedcontinueforsignedvoiddefaultgotosizeofwhiledoifstaticvolstile除此之外,有一些C语言版本(如Turbo C、Microsoft C等)还扩充了一些别的关键字,以便充分利用PC机80x86 CPU的存储结构,以及支持混合语言的程序设计和支持中断处理。表2.2.2列出了PC机上常用的扩充关键字。表2.2.2 PC机上扩充的关键字asm_cs

15、_ ds es sscdeclfarhugeinterruptneerpascal最后我们要指出,C语言预处理中用的一些专用词: defineundefincludeifdefendiflineelififndef 虽然不属于关键字,但为了避免混乱,建议也把它们看成关键字,不要在程序中随便乱用。 2.3 常量的类型 C语言中的常量有下面几种: 2.3.1 整型常量 C语言的整型常量有三种表示形式: (1)十进制形式,如23、0、34。 (2)八进制形式(以0开头表示的数),如0123。 (3)十六进制形式(以0x开头表示的数):如0x123、0xa、0xb、0xd、0xe、0xf。 在整型常量

16、后加I或L后缀,该常量被强制转换为long类型。类似地,后面加u或U将常量强制转换为unsigned类型;且不论何种进制表示,只要其值大于65535,此常量加上U后缀就被强制转换为unsigned long类型。 注:同一常量可使用L或U后缀。 2.3.2 实型常量 C语言的实型常量有两种表示形式: (1)十进制数形式:如0.12、23.3,注意必须有小数点。 (2)指数形式:如123e3或123E3都表示123*103。但应注意:字母e(或E)之前必须有数字且e或E后面指数必须为整数。如e3、2.le3.5、E3等都是不合法的。 2.3.3 字符型常量 C语言的字符常量是用单引号(即撇号)括

17、起来的一个字符,如a、x、F、等是字符常量,但注意小写和大写是不同的。如a与A是不同的字符。 C语言还允许使用一种特殊形式的字符常量,就是以一个“”开头的双字符,常用的特殊字符常量,见表2.3.1:表2.3.1 特殊形式的字符常量字符形式功 能字符形式功 能n回车换行反斜杠字符t横向跳格到下一个输出区双引号v坚向跳格a响铃b向左退一个字符单引号r回车,光标到本行的行首ddd1到3位八进制数代表的字符f走纸换页xhh1到2位十六进制数代表的字符?问号? 表中列出的字符又称为“转义字符”,意思是将反斜杠()后面的字符变成另外的意思。如n中的n不代表字母“n”,而是“换行符”,0或000代表ASCI

18、I值为0的控制字符,“即空操作符”,它将用在字符串的未尾标记字符串的结束。 例2.3.1 对照表2.3.1分析下面程序将输出什么结果。 main( ) printf(Hello!n);printf(We bare); printf(t studing); printf(Clanguge.nwhat are you); printf(doing? n); printf(101102132 abcijkzn); printf(7n); printf(abcdefgt bhij r bk tlmn n); printf(qrsttuvbbwxyzn); 2.3.4 字符串常量 字符串常量是用一对双引

19、号括起来的字符序列,如CHINA、$123.45、A、a、how do you do等。 例2.3.2 下面是屏幕输出字符串的两个程序,试分析它们的输出结果。 第一个程序: main( ) printr(* * * * * * * * * * * * * * * * * * * *n); printf( C语言程序设计n); printr(* * * * * * * * * * * * * * * * * * * *n); 第二个程序: main( ) printf(Lets study C Language,n); printf(n); printf(BASIC Languagen); 不要

20、将字符常量(如a)与字符串常量(如a)相混淆:C语言在处理字符串时自动在字符串的末尾加0作为字符串的结束标志。所以,a包含两个字符a与0。 2.4 变量的类型 2.4.1 变量的类型定义C语言要求在使用变量前,必须先定义类型。其定义方法为:类型标识符 变量标识符表列;其中“类型标识符”为基本类型标识符、构造类型、指针类型、空类型或者是用typedef定义的所有有效的类型。“变量标识符表列”是一个或几个由逗号隔开的变量序列,最后是“;”。变量要先定义类型后使用,其优点是:没事先给出类型说明的标识符不作变量使用;编译系统根据变量的类型说明对变量分配适当的存储单元;系统根据变量的类型说明检查该变量所

21、进行的运算是否合法(见算术运算符%)。C语言的数据类型很丰富。先讨论基本类型的三种变量:(1) 整型变量例如: int x; 定义x为整型变量,存储单元占2个字节 unsigned i,j,k; 定义i、j、k为无符号整型变量,存储单元均占2个字节。 unsigned long a,b,c,d; 定义a、b、c、d为无符号长整型变量(各占4个字节) 例2.4.1 编一个程序,求88与8的和、差、积、商。 main( ) int a,b,sum,min,tim,sep; /* 整型变量说明 */ a=88;b=8; /* 赋值语句 */ sum=a+b; /* 加 */ min=a-b; /*

22、减 */ tim=a*b; /* 乘 */ sep=a/b; /* 除 */ printf(%d+%d=%dn,a,b,sum); /* 显示运算结果 */ printf(%d-%d=%dn,a,b,min); printf(%d*%d=%dn,a,b,tim);printf(%d/%d=%dn,a,b,sep);(2) 实型变量C语言的实型变量分为单精度(float)实型和双精度(double)实型两类。 例如:float x,y; 定义x、y为单精度实型变量(存储单位元各占4个字节),单精度实型变量提供7位有效数字。double f,g,h;定义f、g、h为双精度实型变量(存储单元各占8个

23、字节),双精度实型变量提供16位有效数字。 例2.4.2 输入圆柱体的底面半径与圆柱体的高,求圆柱体的底面周长、底面积、表面积、体积。 main( ) float p,r,h,l,s,sa,v; p=3.1415; printf(Pleace input radius r &.height h:n); scanf(%f%f,&r,&h); 1=2 * p * r; s=p * r * r; sa=2 * s+1*h; v=s * h; printf(The circumference of bottom face of cylinder:1=%6.2fn,1); printf(The area

24、 of bottom face of cylinder:s=%6.2fn,s); printf(The surface of cylinder:sa=%6.2fn,sa); printf(The volume of cylinder:v=%6.2fn,v); (3) 字符型变量例如: char letter, digit;定义letter, digit 为字符型变量(存储单元各占1个字节)字符型变量中只能存放一个字符。 在C语言中,整型(大于等于0而小于等于255)与字符型数据可通用,它可以通过ASCII码进行转换。例2.4.3 编写一个程序,将A赋给变量a,将b赋给变量b,将5赋给变量c,将

25、69赋给变量d,并显示: 1.字符变量a、b、c的值。 2.字符变量a、b、c的ASCII码。 3.整型变量d的值作为ASCII码所对应的字符。 Main( ) char a,b,c; int d; a=A;b=b;c=5;d=69; printf(%c %c %c n,a,b,c); printf(%d %d %d n,a,b,c); printf(%c n,d); 2.4.2 变量赋初值 程序中经常需要对一些变量预先设置初值,C语言规定,可以在定义变量的同时对部分或全部变量进行初始化。其一般形式为: 类型标识符 变量名=常量; 如: int a,b,c=0; 定义a、b、c为整型变量,同时

26、对c赋初值为0。 float f=23.5,m,n;定义f、m、n为单精度实型变量,同时对f赋初值23.5。 char c=s; 定义c为字符型变量,同时对c赋初值s。 int a=b=c=3; 定义a、b、c为整型变量,同时对这三个变量都赋初值3,但这并不表明在程序运行过程中,这三个变量一直是相等的,只是初值相等。 变量初始化不是在编译阶段完成的,而是在程序运行执行本函数时赋以初值的,相当于该函数开始时有一个赋值语句对变量进行赋值。下面列表给出基本变量的取值范围。表2.4.1 基本变量的取值范围数据类型标识符占位取值范围字符char8-128+127整型int16-32768+32767短整

27、型short int16-32768+32767长整型long int32-+无符号整型unsigned int160+65535浮点型float3210-381038双精度型double64103081030825 各类型数据混合运算整型、单精度型、双精度型数据可以混合运算。前已述及,字符型数据可以与整型通用,因此,整型、实型(包括单、双精度)、字符型数据间可以混合运算。例如10+a+1.58765.1234*是合法的。在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算。转换的规则按图2.5.1所示 高 doublefloat long unsigned 低 int char, s

28、hort 图2.5.1 转换规则 图中横向向左的简头表示必定的转换,如字符数据必定先转换为整数,short型转为int型,float型数据在运算时一律先转换成双精度型,以提高运算精度(即使是两个float型数据相加,也先都化成double型,然后再相加。)纵向的箭头表示当运算对象为不同类时转换的方向。例如int型与double型数据进行运算,先将int型的数据转换成double型,然后在两个同类型(double型)数据间进行运算,结果为double型。注意箭头方向只表示数据类型级别的高低,由低向高转换。不要理解为int型先转成unsigned型,再转成long型,再转成double型。如果一个

29、int型数据与一个double型数据运算,是直接将int型转成double型。同理,一个int型与一个long型数据运算,先将int型转换成long型。 换言之,只要有一个运算数据是float型或double型,则另一个数据要先转为double型,结果为double型。如果二个数据中最高级别为long型,则另一数据先转为long型,结果为long型。其它依此类推。假设已指定I为整型变量,f为float变量,d为double型变量,e为long型,有下面式子: 10+a+ i * fd/e运算次序为:进行10+a的运算,先将a转换成整数97,运算结果为107。进行i * f的运算。先将i与f都转

30、成double型,运算结果为double型。整数107与i * f的积相加。先将整数107转换成双精度数(小数点后加若干个0,即107.00000),结果为double型。将变量e化成double型,d/e结果为double型。将10+a+ i * f的结果与d/e的商相减,结果为double型。上述的类型转换是由系统自动进行的。2.6 运算符和表达式 2.6.1 C运算符简介C语言的运算符范围很宽,把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理,例如将赋值符“=”作为赋值运算符,方括号作为下标运算符等。C的运算符有以下几类: 1、算术运算符 (见2.6.2节) 2、关系运算

31、符 ( ! ) 3、逻辑运算符 (!& ) 4、位运算符 ( &) 5、赋值运算符 (=及其扩展赋值运算符) 6、条件运算符 (? :) 7、逗号运算符 (,) 8、指针运算符 (*和&) 9、求字节数运算符 (sizeof) 10、强制类型转换运算符 (类型)11、分量运算符 () 12、下标运算符 ( ) 13、其它 (如函数调用运算符() 2.6.2 算术运算符和算术表达式 一、基本的算术运算符 (加法运算符,或正值运算符。如3+5、+3) (减法运算符,或负值运算符。如52、3) (乘法运算符如3*5) /(除法运算符。如5/3) %(模运算符,或称求余运算符,要求%两侧均为整型数据,

32、如7%4的值为3)。 需要说明,两个整数相除结果为整数,如5/3的结果值为1,舍去小数部分。但是如果除数或被除数中有一个为负值,则舍入的方向是不固定的。例如,5/3在有的机器上得到结果1,有的机器则给出结果2。多数机器采取“向零取整”方法,即5/3=1,5/3=-1,取整后向零靠拢。如果参加运算的两个数中有一个数是实数,则结果是double型,因为所有实数都按double型进行运算。 二、算术表达式和运算符的优先级与结合性 用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称C算术表达式。运算对象包括常量、变量、函数等。例如,下面是一个合法的C算术表达式: a*b/c

33、1.5+a C语言规定了运算符的优先级和结合性(详见2.6.5小节表2.6.1)。在表达式求值时,先按运算符的优先级别高低次序执行,例如先乘除后加减。如ab*c,b的左侧为减号,右侧为乘号,而乘号优先于减号,因此,相当于:a(b*c)。如果一个运算对象两侧的运算符的优先级别相同,如:ab +c,则按规定的“结合方向”处理。C规定了各种运算符的结合方向(结合性),算术运算符的结合方向为“自左至右”,即先左后右,因此b先与减号结合,执行ab的运算,再执行加C的运算。“自左至右的结合方向”又称“左结合性”,即运算对象先与左面的运算符结合。以后可以看到有些运算符的结合方向为“自右至左”,即右结合性(例

34、如,赋值运算符)。关于“结合性”的要领在其它一些高级语言中是没有的,是C的特点之一,希望能弄清楚。 如果一个运算符的两侧的数据类型不同,则会按2.5所述,先自动进行类型转换,使二者具有同一种类型,然后进行运算。 三、可以利用强制类型转换运算符将一个表达式转换成所需类型。例如: (double)a (将a转换成double类型) (int)(x+y) (将x+y的值转换成整型) (float)(5%3) (将5%3的值转换成float型) 其一般形式为 (类型名)(表达式) 注意,表达式应该用括号括起来。如果写成 (int)x+y则只将x转换成整型,然后与y相加。 需要说明的是在强制类型转换时,

35、得到一个所需类型的中间变量,原来变量的类型未发生变化。例如(int)x (不要写成int(x)如果x原指定为folat型,进行强制类型运算后得到一个int型的中间变量,它的值等于x的整数部分,而x的类型不变(仍为float型)。见下例。 main( ) float x; int i;x=3.6; i=(int)x; printf(x=%f,i=%d,x,i); 运行结果如下: x=3.,i=3 x类型仍为float型,值仍等于3.6。 从上可知:有两种类型转换,一种是在运算时不必用户指定,系统自动进行类型转换,如3+6.5。第二种是强制类型转换。当自动类型转换不能实现目的时,可以用强制类型转换

36、。如“%”运算符要求其两侧均为整型量,若x为float型,则“x%3”不合法,必须用:“(int)x%3”。强制类型转换运算优先于%运算,因此先进行(int)x的运算,得到一个整型的中间变量,然后再对3求模。此外,在函数调用时,有时为了使实参与形参类型一致,可以用强制类型转换运算符得到一个所需类型的参数。 四、自增、自减运算符 作用是使变量的值增1或减1,如: +i,-i (在使用i之前,先使i的值加(减)1) i+,i- (在使用i之后,使i的值加(减)1) 粗略地看,+i和i+的作用相当于i=i+1。 但+i和i+不同之处在于+i是先执行i=i+1后,再使用i的值;而i+是先使用i的值后,

37、再执行i=i+1。如果i的原值等于3,则: j=+i; j的值为4 j=i+; j的值为3,然后i变为4。又如: i=3; printf(%d,+i);输出“4”。若改为 printf(%d,i+);则输出“3” 注意: (1)自增运算符(+),自减运算符(),只能用于变量,而不能用于常量或表达式,如5+或(a+d)+都是不合法的。因为5是常量,常量的值不能改变。(a+b)+也不可能实现,假如a+b的值为5,那么自增后得到的6放在什么地方呢?无变量可供存放。 (2)+和的结合方向是“自右至左”。前面已提到,算术运算符的结合方向为“自左而右”,这是大家所熟知的。如果有i+,i的左面是负号运算符,

38、右面是自加运算符。如果i的原值等于3,若按左结合性,相当于(i)+,而(i)+是不合法的,对表达式不能进行自加自减运算。负号运算符和“+”运算符是同优先级,而结合方向为“自右至左”(右结合法),即它相当于(i+),如果有printf(%d,-i+),则先取出i的值使用,输出i的值3,然后使i增值为4。注意(i+)是先用i的原值进行运算以后,再对i加1,不要认为先加完1后再加负号,输出4,这是不对的。 自增(减)运算符常用于循环语句中使循环变量自动加1。也用于指针变量,使指针指向下一个地址。这些将在以后的章节中介绍。 五、有关表达式命名使用中的问题说明 C运算符和表达式使用灵活,利用这一点可以巧

39、妙地处理许多在其它语言中难以处理的问题。但另一方面,有时会出现一些令人容易搞混的问题,因此务必要小心谨慎。 1、在表达式中包含自加或自减运算时,很容易出错。 i+或i什么时候进行自加或自减呢?如果有以下赋值语句,若i原值等于3, k=i+;显然先将i的原值赋给k(k的值等于3),然后i进行自加,执行完此语句后,i的值等于4。如果有以下表达式: (i+)+(i+)+(i+)表达式的值是多少呢?有人认为相当于3+4+5,即12。事实上用Turbo C和MSC系统时它等于9。即先把i的原值(3)取出来,作为表达式中i的值;因此先进行三个i相加,得9。然后再实现自加,i的值变为6。而 k=(+i)+(

40、+i)+(+i)有人以为从左到右使i增值,相当于k=4+5+6,得15。事实上k=18。原因是:+i的自加是在整个表达式求解一开始时最先进行的,即对表达式扫描,先对i进行三次自加,i得6,然后进行k=6+6+6的运算,故得18。2、C语言中有的运算符为一个字符,有的运算符由两个字符组成,在表达式中如何组合呢?如i+j,是理解为(i+)+j呢?还是i+(+j)呢?C编译在处理时尽可能多地(自左而右)将若干个字符组成一个运算符(在处理标识符、关键字时也按同一原则处理),如i+j,将解释为(i+)+j,而不是i+(+j)。 3、C语言中类似上述这样的问题还有一些。例如,在调用函数时,实参数的求值顺序

41、,C标准并无统一规定。如i的初值为3,如果有下面的函数调用: printf(%d,%di,i+)在有的系统中,从左至右求值,输出“3,3”。在多数系统中对函数参数的求值顺序是自右而左,上面printf函数中要输出两个表达式的值(i和i+分别是两个表达式),先计算出i+的值再计算i的值。输出i+,是先输出i的值3然后使i加1变为4,这个4就成了printf函数中第一个参数i的值3。因此上面printf函数输出的是“4,3”。 这些问题不必死记,不同系统的处理方法也不相同,必要时上机试一下即可。但应当知道使用C语言时可能出问题的地方,以免遇到问题时不知其所以然。 使用+和时会出现一些人们“想不到”

42、的副作用,初学者要慎用。 2.6.3 赋值运算符和赋值表达式 一、赋值符号“=”就是赋值运算符,它的作用是将一个数据赋给一个变量。如“a=3”的作用是执行一次赋值操作(或称赋值运算)。把常量3赋给变量a。也可以将一个表达式的值赋给一个变量。 二、如果赋值运算符两侧的类型不一致,但都是数值型或字符型时,在赋值时要进行类型转换。 1、将实型数据(包括单、双精度)赋给整型变量时,舍弃实数的小数部分。如i为整型变量,执行“i=3.56”的结果是使i的值为3。 2、将整型数据赋给单、双精度变量时,数值不变,但以浮点数形式存储到变量中,如将23赋给float变量f,即f=23,先将23转换成23.0000

43、0,再存储在f中。如将23赋给double型变量d,即d=23,则将23补足有效位数字为23.000,然后以双精度浮点数形式存储到d中。 3、字符型数据赋给整型变量时,由于字符只占一个字节,而整型变量为2个字节,因此将字符数据(8位)放到整型变量低8位中。有两种情况: (1)如果所用系统将字符处理为无符号的量或对unsigned char型变量赋值,则将字符的8位放到整型变量低8位,高8位补零。例如:将字符376赋给int型变量i。 (2)如果所用系统将字符处理为带符号的量,若字符最高位为0,则整型变量高8位补0;若字符最高位为1,则高8位全补1。这称为“符号扩展”,这样做的目的是使数值保持不

44、变,如变量c(字符376)以整数形式输出为2,i的值也是24、将带符号的整型数据(int型)赋给long int型变量时,要进行符号扩展,如果int型数据为正值(符号位为0),则long int型变量的高16位补0;如果int型变量为负值(符号位为1),则long型变量的高16位补1,将整型数的16位送到long型低16位中,以保持数值不改变。反这,若将一个long int型数据赋给一个int型变量,只将long ing型数据中低16位原封不动送到整型变量(即截断)。例如: int a; long int b=8; a=b;赋值情况如图2.6.1: b=8: 符号位 a=8: 01000 符号

45、位 图2.6.1 long int 赋给int型变量图如果b=65536(八进制数),则赋值后a值为0。如果b=0(八进制数),赋值后a也是为0。请读者自己分析。 5、将unsigned int型数据赋给long int型变量时,不存在符号扩展问题,只需将高位补0即可。将一个unsigned类型数据赋给一个占字节数相同的整型变量(例如;unsigned intint,unsigned longlong,unsigned shortshort),将undigned型变量的内容原样送到非unsigned型变量中,但如果数据范围超过相应整型的范围,则会出现数据错误。如: unsigned int a

46、=65535; int b; b=a;将a整个送到b中,由于b是int型,第1位是符号位,成了负数(见图2.6.2)。学习补码知识的读者可以知道,b的值为1,可以用 printf(%d,b);来验证一下。 a: 11 11 11 11 11 11 11 11 b: 11 11 11 11 11 11 11 11 符号位 图2.6.2 unsigned int 赋给lont int型变量图 6、将非unsigned型数据赋给长度相同的unsigned型变量,也是原样照赋(连原有的符号位也作为数值一起传送)。如: main( ) unsigned a; int b=1; a=b; printf(%

47、u,a); 运行结果为 65535赋值情况见图2.6.3。如果b为正值,且在032767之间,则赋值后数值不变。 b: 11 11 11 11 11 11 11 11 符号位 a: 11 11 11 11 11 11 11 11 图2.6.3 非unsigned赋给unsigned型变量图 三、复合的赋值运算符 在赋值符“=”之前加上其它运算符,可以构成复合的运算符。如果在“=”前加一个“+”运算符就成了复合运算符“+=”。例如,可以有: a+=3 等价于 a=a+3 x*=y+8 等价于 x=x*(y+8) x%=3 等价于 x=x%3以“a+=3”为例来说明,它相当于使a进行一次自加(3)的操作。即先使a加3,再赋给a。同样,“x*=y+8”的作用是使x乘以(y+8),再赋给x。 为便于记忆,可以这样理解: a+=b (其中a 为变量,b为表达式) a + = b (将有下划线的“a+”移到“=”右侧) a= a+ b (在“=”左侧补上变量名)注意,如果b是包含若干项的表达式,则相当于它有括号。如: x%=y+3 x% = (y+3) x= x%y+3) (不要写成x=x%y+3) 凡是二元(二目)运算符,都可以与赋值符一起组合成复合赋值符。C语言规定可以使用10种复合赋值运算符。即: +=,=,*=,/=,%=,=,&=,=,=后5种是有关位

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论