《第二章数据类型及运算表达式.ppt》由会员分享,可在线阅读,更多相关《第二章数据类型及运算表达式.ppt(86页珍藏版)》请在三一办公上搜索。
1、第二章 数据类型、运算符与表达式,一个程序应包括两个方面的内容:数据的描述。操作步骤,即动作的描述。数据是操作的对象,操作的结果会改变数据的状况。厨师做菜肴,菜谱上一般应包括:配料,指出应使用哪些原料:操作步骤。面对同一些原料可以加工出不同风味的菜肴。,作为程序设计人员,必须认真考虑和设计数据结构和操作步骤(即算法)。因此,著名计算机科学家沃思(Niklklaus Wirth)提出一个公式:数据结构十算法=程序,实际上,一个程序除了以上两个主要要素之外,还应当采用结构化程序设计方法进行程序设计,并且用某一种计算机语言表示。因此,可以这样表示。程序算法十数据结构十程序设计方法十语言工具和环境 也
2、就是说,以上四个方面是一个程序设计人员所应具备的知识。,2.1 的数据类型语言提供的数据结构是以数据类型形式出现的。所谓类型,就是对数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式。不同的类型分配不同的长度和存储形式。,C语言允许使用的数据类型:基本类型整型类型基本整型短整型长整型双长整型字符型布尔型,浮点类型单精度浮点型双精度浮点型复数浮点型,C语言允许使用的数据类型:基本类型枚举类型空类型派生类型指针类型数组类型结构体类型共用体类型函数类型,算术类型,纯量类型,2.2 常量与变量2.2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。常量区分为不同
3、的类型,整型常量:如1000,12345,0,-345实型常量0.34-56.79 0.012.34e3(代表12.34103)字符常量:如?转义字符:如n字符串常量:如”boy”符号常量:#define PI 3.1416,例#define PI 3.1415926main()float s,r,l;r=10.;l=2.*PI*r;s=PI*r*r;printf(l=%f s=%fn,l,s);printf(PI=%fn,PI);,程序中用#define命令行定义PI代表常量3.1415926,此后凡在此文件中出现的PI都代表3.1415926,可以和常量一样进行运算.这种用一个标识符代表一
4、个常量的,称为符号常量,即标识符形式的常量,注意符号常量不同于变量,它的值不能改变,也不能再被赋值。如再用以下赋值语句给PI赋值:PI=3.1416 是错误的。习惯上,符号常量名用大写,变量用小写,以示区别,#define PRICE 30main()int num,total;num=10;total=num*PRICE;printf(“total=%d”,total);,2.2.2变量,变量名,3,变量值,a,其值可以改变的量称为变量。一个变量应该有一个名字,在内存中占据一定的存储单元。在该存储单元中存放变量的值。请注意区分变量名和变量值这两个不同的概念。,2.2.3 常变量,常变量具有变
5、量的基本属性:有类型,占存储单元,只是不允许改变其值。举例 const int a=3;注意:1、常变量是有名字的不变量,常量是没有名字的不变量。2、符号常量不分配存储单元,而常变量占用存储单元,2.2.3标识符标识符:用来标识变量名、符号常量名、函数名、数组名、类型名、文件名的有效字符序列称标识符(identifier),简单他说,标识符就是一个名字。C语言规定标识符只能由字母、数字和下划线三种字符组成,且第一个字符必须为字母或下划线。如,sum,average,class,day,month,student_name,下面是不合法的标识符和变量名:M.D,$123.#33,3D64,a b
6、 注意:1、大写字母和小写字母被认为是两个不同的字符。习惯上,变量名用小写字母表示,以增加可读性。2、标识符长度建议在4-25个字符之间。,在选择变量名和其它标识符时,应注意做到“见名知意”,即选有含意的英文单词(或其缩写)作标识符,如count,name,day,month,class,city,country等,以增加程序的可读性。这是结构化程序的一个特征。在语言中,要求对所有用到的变量作强制定义,也就是“先定义,后使用”,否则,在编译时会指出有关“出错信息”。,关键字又叫保留字,是C编译系统已规定某些标识符有特定含义,用户只能按规定使用。在程序中定义标识符时,不能与关键字同名。,什么是关
7、键字,在C中共有32个基本的关键字,都是用小写字母组成的。用户不能用。,见 P.378,2.3 整型数据2.3.1 整型常量 整型常量即整常数。语言中整常数可用以下三种形式表示:十进制整数。如、一、。八进制整数。以O开头的数是八进制数。如O123表示八进制数123,即(123)8等于十进制数。-011表示八进制数-11,即十进制数-9。,十六进制整数。以开头的数是进制数。,代表进制数,即()160=。一等于十进制数一。main()int a=0123,b=0 x123;printf(“a=%d,b=%d”,a,b);,2.3.2 整型变量 一、整型变量的分类整型变量可分为:基本型、短整型、长整
8、型和无符号型四种。基本型,以int表示。2.短整型,以short int表示,或以short表示。3.长整型,以1ong int表示,或以1ong表示。4.双长整型,以long long int表示,C99新增的,4.无符号型,存储单元中全部二进位(bit)用作存放数本身,而不包括符号。无符号型中又分为无符号整型、无符号短整型、无符号长整型和无符号双长整型,分别以unsigned int,unsigned short,unsigned long,unsigned long long 表示。无符号型变量只能存放不带符号的整数。,一个无符号整型变量中可以存放的数的范围比一般整型变量中正数的范围扩大
9、一倍。如果整型量在内存中占2个字节(16位),则int型变量数的范围为:-32768 32767.unsigned int型变量的范围为0 65535,数值|补码-|-0|00000000-1|11111111-2|11111110-3|11111101-4|11111100.|.(往下不断减1).-127|10000001-128|10000000,-|-1|00000001 2|00000010.|.|.(往下不断加1).|.126|01111110 127|01111111,二、整型变量的定义 前已提到,C规定在程序中所有用到的变量都必须在程序中指定其类型,即“定义”。例如:int a,
10、b;/指定变量a,b为整型)unsigned short c,d;/指定变量c,d为无符号短整型)1ong e,f;/指定变量e,f为长整型)对变量的定义,一般是放在一个函数的开头部分,例2.2main()int a,b,c,d;/指定a,b,c,d为整型变量 unsigned u;/指定为无符号整型变量a=12;b=-24;u=10;c=a+u;d=b+u;printf(c=%d d=%d,c,d);运行结果为 c,d=-14 结论:可以看到不同种类的整型数据可以进行算术运算。,例如:#includemain()short int a,b;a=32767;b=a+1;printf(“%d%d
11、”,a,b);,三、整型常量的类型 在将一个整型常量赋值给不同类别的整型变量时请注意以下几点:1.一个整常量,如果其值在一32768+32767范围内。认为它是int型,它可以赋值给int型和short int型等变量。一个整常量,如果其值超过了上述范围,而在一21474836482147483647范围内,则认为它是1ong int型。可以将它赋值给一个1ong int型变量。,3如果某一计算机系统的版本确定的short int 与int型数据在内存中占据的长度相同,则它的表述范围与int型相同,因此一个int型的常量也同时是一个short int型常量,可赋给int型或short int型
12、变量。4.常量中无unsigned型。但一个非负值的整常量可以赋值给unsigned型整变量,只要它的范围不超过变量的表述范围即可,例如,将50000赋给一个unsigned int型变量是可以的,而将70000赋给它是不行的(溢出)。,5.不能将负数赋值给无符号整型。unsigned short a=-1;printf(“%dn”,a);6.在一个整常量后面加一个字母l或L则认为是1ong int型常量。例如123l、432L.,2.4 实型数据2.4.1 实型常量 实数在语言中又称浮点数,实数有两种表示形式:1.十进制数形式。它由数字和小数点组成(注意必须有小数点)。0.123、.123、
13、123.0、123.、0.0都是十进制数形式。2.指数形式,如123e3或123E3都代表123X103但注意字母e(或E)之前必须有数字。且e后面指数必须为整数,如e3、2.1e3.5、e等都不是合法的指数形式。,2.4.2 实型变量 C实型变量分为单精度(float型)和双精度(double型)两类,对每一个实型变量都应在使用前加以定义。如:float x,y;/指定x,y为单精度实数 doublez;/指定z为双精度实数 在一般系统中,一个float型数据在内存中占4个字节(32位)一个double型数据占8个字节。单精度实数提供6位有效数字,双精度实数提供有效数字。数值的范围随机器系统
14、而异。,实型变量的分类,注意:长双精度在VC+中长度为8字节数,应当说明,实型常量不分float型和double型。一个实型常量可以赋给一个float型或double型变量。根据变量的类型截取实型常量中相应的有效位数字.假如a已指定为单精度实型变量:float a;a=111111.111;由于float型变量只能接收6位有效数字,因此最后三位小数不起作用。如果改为double型,则能全部接收上述位数字并存储在变量中。,2.5 字符型数据2.5.1字符常量 C的字符常量是用单引号(即撇号)括起来的一个字符,如a,x,D,?,$等都是字符常量,注意,a和A是不同的字符常量。除了以上形式的字符常量
15、外,C还允许用一种特殊形式的字符常量,就是以一个”开头的字符序列.例如,前面已经遇到过的,在printf函数中的n,它代表一个“换行”符。,这种非显示字符难以用一般形式的字符表示,故规定用这种特殊形式表示。常用的以“”开头的特殊字符见表,表中列出的字符称为“转义字符”,意思是将反斜杠()后面的字符转变成另外的意义。如“n”中的“n”不代表字母n而作为“换行”符。表中最后第二行是用ASCII码(八进制数)表示的一个字符,例如101代表字符A。用376,代表图形字符。用表中的方法可以表示任何可输出的字母字符、专用字符、图形字符和控制字符。请注意0或000是代表ASCII码为0的控制字符,即“空操作
16、”字符。它将用在字符串中。,2.5.2 字符变量 字符型变量用来存放字符常量,注意只能放一个字符。字符变量的定义形式如下:char c1,c2;它表示c1和c2为字符型变量,各可以放一个字符,因此可以用下面语句对c1、c2赋值:c1=a;c2=b;一般以一个字节来存放一个字符,或者说一个字符变量在内存中占一个字节。,253 字符数据在内容中的存储形式及其使用方法 将一个字符常量放到一个字符变量中,实际上并不是把该字符本身放到内存单元中去,而是将该字符的相应的ASCII代码放到存储单元中。书P377,例如字符a的ASCII代码为97,b为98,在内存中变量c1、c2的值如图2.2(a)所示。实际
17、上是以二进制形式存放的,如图2.2(b)所示。c1 c2 97 9801100001 01100010 2.2(a)2.2(b),【例2.4】main()char c1,c2;c1=97;c2=98;printf(%c%c,c1,c2);,“%c”是输出字符的格式符。程序输出:a b,【例2.5】#includemain()char c1;int c2;c1=97;c2=a;printf(%c,%dn,c1,c1);printf(%c,%dn,c2,c2);,在内存中,字符数据以ASCII码存储,它的存储形式与整数的存储形式相类似。C语言使字符型数据和整型数据之间可以通用。注意:字符数据只占一
18、个字节,它只能存放0-255的整数 一个字符数据既可以以字符形式输出,也可以以整数形式输出。以字符形式输出时,需要先将存储单元中的ASCII码转换成相应字符,然后输出。以整数形式输出时,直接将ASCII码作为整数输出。也可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算。,【例2.6】main()char c1,c2;c1=a;c2=b;c1=c1-32;c2=c2-32;printf(%c%c,c1,c2);它的作用就是将两个小写字母转换成大写字母。因为a的ASCII码为97,A的为65,b为98,B 为66。从ASCII代码表中可以看到每一个小写字母都比它相应的大写字母
19、的ASCII码大32。,2.5.4 字符串常量 字符常量是由一对单引号括起来的单个字符。字符串常量是一对双引号括起来的字符序列。如:“How do you do。”,”CHINA”,”12345”都是字符串常量.一个字符串可以利用printf输出。如 printf(”How do you do.”);,不要将字符常量与字符串常量混淆。a是字符常量,”a”是字符串常量,二者不同。假设 c被指定为字符变量:char c;c=a;是正确的。而 c=”a”;是错误的。c”CHINA”,也是错误的。不能把一个字符串赋给一个字符变量。在C语言中没有专门的字符串变量,字符串如果需要存放在变量中,需要用字符数
20、组来存放,即用一个字符型数组来存放一个字符串,C规定:c规定以字符0作为字符串结束标志。0是一个ASCII码为0的字符,“空操作字符”,即它不引起任何控制动作,也不是一个可显示的字符。CHINA”实际上在内存中是 C H I N A0它的长度(内存中)不是5个字符,而是6个字符,最后一个字符为0。但在输出时不输出0。但是实际长度还是 5个字符。利用strlen函数计算(#include string.h),例如在printf(”How do you do。”)中,输出时一个一个字符输出,直到遇到最后的0字符,就知道字符串结束,停止输出。注意:在写字符串时不必加0,否则画蛇添足0,字符是系统自动
21、加上的。,a和“a”究竟区别:(1)定界符不同:字符常量使用单引号,而字符串常量使用双引号;(2)长度不同:字符常量的长度固定为1,而字符串常量的长度,可以是0,也可以是某个整数;(3)存储要求不同:字符常量存储的是字符的ASCII码值,而字符串常量,除了要存储有效的字符外,还要存储一个结束标志0。,字符常量与字符串常量的比较,26变量赋初值程序中常需要对一些变量预先设置初值。,一般形式:,类型说明符 变量1=值1,变量2=值2,;,1.可以在定义变量时同时使变量初始化。如:int a=3;/指定a为整型变量,初值为3 float f=3.56;/指定f为实型变量,初值为356,2.可以使被定
22、义的变量的一部分赋初值。如:int a,b,c=5;表示a、b、c为整型变量,只有c初始化,值为5。3.如果对几个变量赋以同一个初值,不能写成:int abc=3;()而应写成:int a3,b3,c=3;,初始化不是在编译阶段完成的,而是在程序运行时执行本函数时赋以初值的。例如 int a=3;相当于:int a;指定a为整型变量 a=3;赋值语句,将3赋予a,27各类数值型数据间的混合运算 整型、单精度型、双精度型数据可以混合运算。前已述及,字符型数据可以与整型通用,因此,整型、实型(包括单、双精度)、字符型数据间可以混合运算。例如 10+a+1.5-8765.1234b是合法的。在进行运
23、算时,不同类型的数据要先转换成同一类型,然后进行运算。转换的规则按图2.3所示,doublefloat long unsigned int char,short 图2.3,说明:1.图中横向向左的箭头表示必定的转换;2.纵向的箭头表示当运算对象为不同类型时转换的方向。3.注意箭头方向只表示数据类型级别的高低,由低向高转换.,例如:假设已指定i为整型变量,f为float变量,d为double型变量,e为1ong型,有下面式子:10十ai*f-d/e,上述的类型转换是由系统自动进行的。,2.8算术运算符和算术表达式2.8.1 C运算符简介C的运算符主要有以下几类。1算术运算符 2关系运算符(=|&
24、),5赋值运算符(=及其扩展赋值运算符)6条件运算符(?:)指针运算符(*和&)在本章只介绍算术运算符和赋值运算符,在以后各章中结合有关内容将陆续介绍其它运算符。运算符见书P365。,2.8.2 算术运算符和算术表达式 一、基本的算术运算符 十(加法运算符,或正值运算符。如35、3)一(减法运算符,或负值运算符,如5一2、一3)*(乘法运算符。如3*5)(除法运算符。如53)(模运算符,或称求余运算符,要求两侧均为整型数据)。,说明:1、两个整数相除结果为整数,如5/3的结果值为1,舍去小数部分。2、但是如果除数或被除数中有一个为负值,则舍入的方向是不固定的。例如,一53在有的机器上得到结果-
25、1,有的机器则给出结果一2。多数机器采取“向零取整”方法。3、如果参加运算的两个数中有一个数为实数,则结果是double型,因为所有实数都按double型进行运算。,二、算术表达式和运算符的优先级与结合性 用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子,称C算术表达式。运算对象包括常量、变量、函数等。例如,下面是一个合法的C算术表达 a*bc一15十a,C语言规定了运算符的优先级和结合性。优先级:运算符的高低次序执行。结合性:运算符的结合方向。自左至右的结合方向又称“左结合性”,即运算对象先与左面的运算符结合.自右至左的结合方向又称“右结合性”,即运算对象先与右面的
26、运算符结合.,在求表达式值时,先按运算符的优先级别高低次序执行,如果在一个运算对象两侧的运算符的优先级别相同,则按规定的“结合方向”处理如:a-bc*d。如果一个运算符的两侧的数据类型不同,先自动进行类型转换,使二者具有同一种类型,然后进行运算。,三、可以利用强制类型转换运算符将一个表达式转换成所需类型。例如:(double)a(将a转换成double类型)(int)(x+y)(将调x+y的值转换成整型)其一般形式为(类型名)(表达式)注意:类型和表达式应该用括号括起来。如果写成(int)x+y则只将x转换成整型,然后与y相加。,需要说明的是在强制类型转换时,得到一个所需类型的中间变量,原来变
27、量的类型未发生变化。,例如 main()float x;x=3.6;i=(int)x%2;printf(“xf,i=d”,x,i);,从上可知:有两种类型转换,一种是在运算时不必用户指定,系统自动进行类型转换,如3+6.5。第二种是强制类型转换,当自动类型转换不能实现目的时,可以用强制类型转换。,四、自增、自减运算符 作用是使变量的值增1或减1,如:粗略地看,+i和i+的作用相当于ii+1。但+i和i+不同之处在于+i是先执行i=i+1后,再使用i的值;而i+是先使用i的值后,再执行i=i+1。,+i i自增1后再参与其它运算-i i自减1后再参与其它运算 i+i参与运算后,i的值再自增1 i
28、-i参与运算后,i的值再自减1,如果i的原值等于3,则:j+i;j的值为4 j=i+j的值为3,然后i变为4又如:i=3;printf(”d”,+i);若改为 printf(”d”,i+);,注意:(1)自增运算符(+),自减运算符(-),只能用于变量,而不能用于常量或表达式。如5+或(a+b)+都是不合法的。因为5是常量,常量的值不能改变。(a+b)+也不可能实现,理由:无变量可供存放。(2)+和-的结合方向是“自右至左”。见附录。例如:-i+,五、有关表达式使用中的问题说明1在表达式中包含自加或自减运算时,很容易出错。1)如果有以下表达式:i=3;(i+)+(i+)+(i+)事实上用Tur
29、boC和VC系统时它等于9。即先把i的原值(3)取出来,作为表达式中i的值;因此先进行三个i相加,得9。然后再实现自加,i的值变为6。,2)k(+i)+(+i)+(+i)原因是:+i的自加是在整个表达式求解一开始时最先进行的,即对表达式扫描,先对i进行三次自加,i得6,然后进行k=6+6+6的运算,故得18。注意:不同编译系统不同结果。结论:请不要在一个表达式中对一个变量进行多次诸如i+或+i等运算.,2C语言中有的运算符为一个字符,有的运算符由两个字符组成,在表达式中如何组合呢?如 i+j,是理解为(i+)+j 呢?还是i+(+j)?C编译在处理时尽可能多地(自左而右)将若干个字符组成一个运
30、算符,如 i+j,将解释为(i+)+j,而不是i+(+j)。,3C语言中类似上述这样的问题还有一些。例如,在调用函数时,实参数的求值顺序,C标准并无统一规定。如i的初值为3如果有下面的函数调用:printf(“d,d”,i,i+)在有的系统中,从左至右求值,输出“3,3”。在多数系统中对函数参数的求值顺序是自右而左,,2.9赋值运算符和赋值表达式 一、赋值符号“”就是赋值运算符,它的作用是将一个数据赋给一个变量。如“a3”的作用是执行一次赋值操作(或称赋值运算)。把常量3赋给变量a,也可以将一个表达式的值赋给一个变量。二、如果赋值运算符两侧的类型不一致,但都是数值型或字符型时,在赋值时要进行类
31、型转换。,将实型数据(单、双)赋给整型变量,舍弃实数的小数部分(取整数部分,而并非四舍五入)。,int m;m=2.6;,m=2;,将整型数据赋给实型(单、双)变量,数值不变,但以浮点数形式存储到变量中。,float m;m=10;double n;n=10;,m=10.00000;(7位有效数字)n=10.00000000000000;(16位有效数字),将double型数据赋给float变量,截取其前面7位有效数字,存放到float变量的存储单元(32位)中,但应注意数值范围不能溢出。,double n;n=123.456789e100;float m;m=n;,m出现溢出;,字符型数据赋
32、给整型变量,将字符数据(8位)放到 整型变量低8位中。,无符号:,0,0,0,0,0,0,1,0,将int、short、long型数据赋给一个char型变量,将其低8位送到char型变量(即截取)。,将int型数据赋给long型变量,分有无符号位两种情况处理:无符号位,则高位补0;有符号位,则高位补符号位,以保持数据值不改变。,将非unsigned型数据赋给长度相同的unsigned型变量,符号位作为数值一起传送。,-32766,32770,总结:多位少位截断;少位多位:无符号,高位补0,有符号,高位补符号位。,三、复合的赋值运算符 在赋值符“=”之前加上其它运算符,可以构成复合的运算符。例如
33、,a+=3 a=a+3;x*=y x=x*y;x%=3 x=x%3;凡是二元运算符,都可以构成复合赋值符号。,注意:a+b 如果b是包含若干项的表达式,则相当于它有括号。即a=a+(b)如:x=y3 x=(y3)x=x%(y3)(不要写成x=xy3)C采用这种复合运算符,一是为了简化程序,使程序精练,二是为了提高编译效率,能产生质量较高的目标代码。,四、赋值表达式1、由赋值运算符将一个变量和一个表达式连接起来的式子称为“赋值表达式”。它的一般形式为(变量)(赋值运算符)(表达式)2、对赋值表达式求解的过程是:将赋值运算符右侧的“表达式”的值赋给左侧的变量。赋值表达式的值就是被赋值的变量的值。3
34、、赋值运算符按照“自右而左”的结合顺序。,a=b=c=5 a=5(c=6)a=(b=4)(c=6)a=(b10)/(c=2)4、赋值表达式也可以包含复合的赋值运算符。如 a+=a-=a*a,2.10逗号运算符和逗号表达式 C语言提供一种特殊的运算符逗号运算符。用逗号将两个表达式连接起来。如 3十5,6十8称为逗号表达式。1、结构:逗号表达式的一般形式为 表达式1,表达式2 2、求解过程先求解表达式1,再求解表达式2。整个逗号表达式的值是表达式2的值。,判断以下表达式的值:1.a=3*5,a*42.x=(a=3,6*3)3.x=a=3,6*a 注意以下两个语句的区别:printf(“%d,%d,%d”,a,b,c);printf(“%d,%d,%d”,(a,b,c),b,c);,注意:并不是任何地方出现的逗号都是作为逗号运算符。,