《顺序结构程序设计》PPT课件.ppt
第2章顺序结构程序设计,2.1 C程序结构2.2 基本数据类型、变量与常量2.3 赋值运算符与赋值表达式2.4 算术运算符与算术表达式2.5 逗号运算与逗号表达式,主要内容,2.6 运算符的优先级与结合性2.7 混合运算时数据类型的转换2.8 语句和块2.9 数据的输入与输出2.10 顺序结构程序设计综合举例,主要内容(续),2.1 C程序结构,举例介绍C语言的程序结构。例2-1 从键盘输入半径,求圆的周长和面积。,算法思路:radius:存放从键盘输入的半径;计算周长:perimeter=2*radius*PI;计算面积:area=PI*radius*radius,输出perimeter和area的值,不确定性,列公式,#include double PI=3.14;void main()int radius;double perimeter,area;printf(Input a radius:);scanf(%d,声明变量radius,提示输入,输入数据赋给radius,计算周长和面积,输出结果,预处理命令,全局变量声明,函数定义,2.1 C程序结构,C源程序由三个要素组成:(1)预处理命令。C编译程序对源程序编译前,先由预处理器对预处理命令进行预处理。(2)全局声明。包括全局变量声明和函数原型声明。(3)函数定义。一个C语言程序由一个或多个函数组成的,其中只能有一个main函数。函数由一组语句组成。比语句更小的语法单位:表达式、变量、常量和关键字等。,2.1.1 C字符集,大小写的英文字母:AZ,az数字字符:09特殊字符:空格!%.,(),2.1.2 词法记号,关键字(Keyword)又称为保留字,C语言预定的具有固定含义的一些单词 例如:数据类型修饰符int,控制语句return等,auto break case char continue const default double do else float for if int long NULL return switch shortsigned true this unsigned void while,2.1.2 词法记号,标识符(Identifier)以字母和下划线开始,大小写敏感,最长32个字符。以大写字母、小写字母、下划线或数字09组成。直观,见名知意,便于记忆和阅读最好使用英文单词或其组合,忌使用汉语拼音 不宜混淆 如1与l,o与0不允许使用关键字作为标识符的名字 int,float,for,while,if等,例:判断下列标识符号合法性,并标出不合法的标示符。sum Sum M.D.John day Date 3days student_name#33 lotus_1_2_3 char ab _above$123,M.D.John,3days,#33,char,$123,ab,2.1.2 词法记号,2.1.2 词法记号,运算符(Operator)34种,详见P200页附录A分隔符(Separator)空格、回车/换行、逗号等 其它符号 大花括号和/*和*/是程序注释所需的定界符数据(Data)变量(Variable)常量(Constant),2.2 数据类型、常量和变量,2.2.1 基本数据类型2.2.2 常量2.2.3 变量2.2.4 符号常量2.2.5 指针与指针变量,2.2 数据类型、常量和变量,数据为什么要区分类型?不同类型的数据代表不同的数据表示形式合法的取值范围占用内存空间大小可参与的运算种类,数据类型(Data Type),如何衡量数据类型所占空间大小?,常用的单位如下:b,B,KB,MB,GB,TB bit,中文叫法:位Byte,中文叫法:字节Kilobyte(KB),中文叫法:KMegabyte(MB),中文叫法:兆Gigabyte(GB),中文叫法:GTerabyte(TB),中文叫法:T,1 TB=1,024 GB,1 GB=1,024 MB,1 MB=1,024 KB,1 KB=1,024 B,1 B=8 b,如何衡量数据类型所占空间大小?,一个位有多大?只能是0或者1,这叫二进制一个字节有多大?保存一个字符(英文字母、数字、符号)ASCII(美国标准信息交换码)编码见附录A,常用字符与ASCII码对照表两个字节保存一个汉字GB编码可以表示0255之间的整数,2.2.1 基本数据类型,表2-1 C的基本数据类型(32位机),整型(integer),整型:有符号整数,允许取值为整数 如:123,567整型的分类:整型(int):占4个字节短整型(short int):占2个字节,通常简写为short长整型(long int):占4(8)个字节,通常简写为long,数据类型修饰符,signed用来修饰char、int、short和long,说明他们是有符号的整数(正整数、0和负整数)。有符号数在计算机内以二进制补码形式存储的,最高位表示符号位(0为正数,1为负数)。一般缺省都是有符号的,所以这个修饰符通常省略。,int型:,最大:32767,最小:-32768,数据类型修饰符,unsigned用来修饰char、int、short和long,说明他们是无符号的整数(正整数和0)。无符号型在机内只能存放正数,最高位也来表示数值的。当数据占用同样内存位数时,无符号型数值范围比有符号数扩大一倍。,数据类型修饰符,unsigned int型:,最大:65535,最小:0,扩充的整型类型,有符号基本整型 signed int;无符号基本整型 unsigned int;有符号短整型 signed short int;无符号短整型 unsigned short int;有符号长整型 signed long int;无符号长整型 unsigned long int;,二进制存放与溢出,(1)10=(0000 0000 0000 0001)2,(-1)10=,(1111 1111 1111 1111)2,(65535)10=,(1111 1111 1111 1111)2,当65535按unsigned int型理解时,仍为65535;而当按int型理解时,被当作-1的补码。,字符型(char),字符型char的取值为单个字符。例如:A、用ASCII编码表示一个字符,每个字符占用1个字节,总共可以表示256个不同的字符。char 类型前可用signed和unsigned加以修饰。例如:char ch=127;signed char ch=-128;unsigned char ch=255;思考:unsigned char 范围?,浮点型(float point),浮点类型:允许取值为带小数的实数双精度浮点型double单精度浮点型float 如 123.46double比float的精度更高(即小数的有效位数更多),表示数据的范围也更大。,2.2.2 常量,常量(Constant)在程序执行过程中其值不变的量。常量包括以下几种:整型常量浮点常量字符常量字符串常量,整型常量(short,int,long),整型常量18、-31long int型常量 123l、123L、123456l、123456Lunsigned int型常量 123u、123U整型常量的类型根据其值所在范围确定其数据类型在整型常量后加字母l或L,认为它是long int 型常量,整型常量的表示形式,整型常量的表示形式:十进制八进制十六进制,整型常量的表示形式,十进制形式:若干个09的数字 如:100,-50,0 八进制形式:以0开头的若干个07数字 如:0123 表示十进制数 83,-011 表示十进制数-9。010和10大小不一样,整型常量的表示形式,十六进制形式:用0 x或0X开头的若干个 09,af,AF的数字 如:0 x2F 表示十进制的数字47。0 x123 表示十进制数291,-0X12 表示十进制数-18。,例:12与12L,例:30000 为int型 65536 为long int 型,整型常量的表示形式,例:0524 为int型,在内存中是如何表示的?,01010100,00000001,4,2,5,例:01736L 为long int 型,11011110,00000011,00000000,00000000,6,3,7,1,注意事项,Example:#include void main()short int a;printf(Input:);scanf(%d,运行结果:Input:12345 a=12345 Input:1234567 a=-10617,整型整数 short int 的范围:-32768+32767,Because:12345的补码是0011000000111001 1234567的补码是100101101011010000111 截去多余部份(超过2个字节的左边部分)后 其原码为 1010100101111001(-10617),可用下图表示:32767 32766 32765-32766-32767-32768,输入(Input:)输出(a=)32767 32767 32768-32768 32769-32767 32770-32766-32768-32768-32769 32767-32770 32766,有趣的结果,何谓类型溢出(Overflow)?,C语言直接提供的任何类型都有取值范围。当向其赋超过此范围的数值,就会产生数值溢出,得到一个不正确的结果。short int的范围是-3276832767如果超出取值范围,给它一个小于-32768或者大于32767的数会如何呢?,小蛇能吞下大象吗?,类型溢出的解决方案?,解决方案:预先估算运算结果的可能范围,采用取值范围更大的类型。1+2+3+1!+2!+3!+13+23+33+如果不需要处理负数,则采用无符号类型。在运算还没开始之前就判断运算数是否在合理的取值范围内。如果超出,则停止运算,转错误处理。,浮点型常量(float,double),浮点型常量:可以含有小数部分的数值常量。根据占用内存长度的不同,分为:单精度浮点常量:占用32位内存,用F、f表示。如:19.4F,3.0513E3f,8701.52f双精度浮点常量:占用64位内存,用带D或d或不加后缀(缺省)的数值表示 如:2.433E-5D,700041.273d,3.1415。long double型常量 123.45l、456.78L、4.5e3L因为字母l和数字1容易混淆,所以当用l做后缀时,常使用大写形式,浮点型常量(float,double),浮点常量两种表示形式:十进制小数形式和指数形式。十进制小数形式:包括符号+与-,09十个数字以及小数点.。如:0.123,1.23,123.0。指数形式:包括符号+与-,09十个数字,小数点.以及e(或E)。如:0.123e3 表示0.123103-35.4E-5 表示-35.410-5,其中e或E之前必须有数字,且e或E后面的指数必须为整数。,如:e-5,1.2E-3.5 不正确,浮点型常量(float,double),例:,/下列程序的功能是将10个实型数0.1进行累加,然后将累加结果输出。#include stdio.hvoid main()int k;/*定义整型变量k*/double x,z;/*定义双精度是型变量x与z*/z=1.0;/*实数1.0赋给变量z*/x=0.0;for(k=0;k10;k+)x=x+0.1;/*10个0.1累加到变量x中*/printf(z=%20.17fn,z);/*输出变量z的值*/printf(x=%20.17fn,x);/*输出变量x的值*/,字符常量(Character),字符常量:用一对单引号括起的单个字符。一个字符用一个字节存储。字符常量的值:该字符的ASCII码值,如:A 65,a 97,0 48,n 10,如:101-A 012-n 376-x61-a 60-0 483-(),例:A-101-x41-65,字符常量(Character),就是一个普通整数,也可以参与各种数学运算每个字符具有一个0255之间的数值,可查ASCII表注意:1和整数1的区别字符1只是代表一个形状为1的符号,在需要时按原样输出,在内存中以ASCII码形式存储,占1个字节整数1是以整数存储方式,占1个字节,0 0 0 0 0 0 0 1,字符常量(Character),转义字符用开头的字符 例如,n,代表1个字符一些特殊字符(无法从键盘输入或者另有它用)用转义字符表示,含义如表2-2。,表2-2 常用转义字符,转义字符举例,例1:void main()printf(101 x42 Cn);printf(C Programn);printf(Turbo C);,运行结果:(屏幕显示)A B CC ProgramTurbo C,转义字符举例,例2:void main()printf(Yb=n);,运行结果:屏幕显示:=打印机输出:,例3:#include void main()printf(How are you?n);printf(I am fine.nn);/*横向跳格符t,使跳到下一个输出区*/printf(How are you?t);printf(I am fine.nn);/*退格符b,使当前的输出位置退一格,即输出的起始位置左移一位*/printf(How are you?n);printf(bI am fine.nn);/*回车符r,使当前输出位置回到本行开头*/printf(I am fine.);printf(rHow are you?nn);/*多个转义字符的混合运用*/printf(note:n a stibbkrpn);,什么时候要使用转义字符?,转义字符只在特殊情况下才使用:C程序中需要实现某些特定打印或显示动作时 如 printf(123t56n);C程序中需要打印或显示以下三个字符时(斜杠)(双引号)(单引号)如 printf(Youre a a bad egg!);C程序中需要打印或显示ASCII表中非键盘字符时 如 printf(Look 16 and x80!);,注意:使用转义字符时,后的八进制或十六进制数不应大于char类型所允许的范围(十进制值256)。,字符串常量(String),用双引号括起的一串字符(可以0个)I am a string表示空字符串转义字符也可以在字符串中使用引号只作为字符串开始和结束的标志C语言内部自动用0表示字符串的结束除注释外,是唯一可以出现中文的地方x和x是不同的里定义了一系列专门的字符串处理函数,逻辑(布尔)型常量 boolean,在程序控制中经常用到布尔常量。例如:If(条件)动作1 else 动作2布尔常量的值:true(真)和false(假)。C语言中将布尔类型映射为数值类型:true 用非0的整数表示 false 用0表示,如:3+1=4 结果为true,通常表示1。int a=23 结果为false,通常表示0。,2.2.3 变量,变量在程序执行过程中其值可以改变的量。因此用来记录运算中间结果或保存数据。变量的声明:,数据类型 变量名1,变量名2,变量名n;,决定分配字节数和数的表示范围,合法标识符,short,int,long,float,double,char,unsigned 复合类型,2.2.3 变量,例:int a,b;double data;,编译时,对变量声明语句将根据其类型分配存储空间。变量的名实际上对应空间的地址,变量的值对应空间的内容。在对程序编译连接时由编译系统给每一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。,2.2.3 变量,基本类型与变量的分配空间,2.2.3 变量,例如:short s;/给s变量分配两个字节,占用2000-2001单元 s=1234;,图2-1 变量与内存单元的映射关系,2.2.3 变量,变量的使用:先申明,后使用,例1:int student;stadent=19;,变量名和变量值的概念,2.2.3 变量,例2:float a,b,c;c=a%b;,2.2.3 变量,变量定义位置:一般放在函数开头,void main()int a,b=2;float data;a=1;data=(a+b)*1.2;printf(data=%fn,data);,2.2.3 变量,变量的初始化:声明变量的同时指定变量初值格式:数据类型 变量名=初始值;不被初始化的变量,其值为危险的随机数,char esc=a;int i=1;int sum=0;float eps=1.0e-5;,2.2.3 变量,例如:利用变量t交换变量x和y的值t=x;x=y;y=t;,t,y,x,变量的值主要通过赋值运算改变。,使用变量要注意,不要对变量所占的内存空间字节数想当然用sizeof获得变量或者数据类型的长度sizeof运算符:返回操作数存储空间的大小使用形式:sizeof(type)或 sizeof(var_name)求出的结果为表达式值所属类型或者类型占用的字节数sizeof运算符也可以出现在表达式中。例如,x=sizeof(float)-2;printf(%d,sizeof(double);参见教材P22页例2-2,注意!,为什么要用sizeof获得类型或变量的字长?,因为同种类型在不同的平台其占字节数不尽相同。比如int在16位、32位和64位系统分别占2、4和8个字节。现象与危害:在平台间移植时会出现问题,导致数据丢失或者溢出。解决方案:用,并且只用sizeof获得字长。,变量的类型,整型变量定义形式:int 变量表列;实型变量单精度定义形式:float 变量表列;具有67位有效数字双精度定义形式:double 变量表列;具有1516位有效数字,变量的类型,字符型变量用于存放字符型常量定义方式:char 变量表列;字符变量存放字符ASCII码char与int数据间可进行算术运算,例:a=D;/*a=68;*/x=A+5;/*x=65+5;*/s=!+G;/*s=33+71;*/,没有字符串变量,用字符数组存放,字符量与字符串的存储区别,字符 A,65,01000001,占1字节,65 78 83 73 32 67 0,A N S I C,字串 ANSI C,占7个字节,实型数据提供的有效数字位数,#include void main()float a;double b;a=123456.789e4;b=123456.789e4;printf(%fn%fn,a,b);,float型数据提供7位有效数字,double型数据提供16位有效数字,使用不当导致舍入误差,char型与int型之间的关系,例:小写字母转换为大写字母,#include void main()char ch=b;printf(%c,%dn,ch,ch);ch=b-32;printf(%c,%dn,ch,ch);,b,98B,66,#include void main()char ch=b;printf(%c,%dn,ch,ch);ch=b-(a-A);printf(%c,%dn,ch,ch);,b,98B,66,一个整型数据占4B,而字符型数据只占1B(只能存放0255范围内的整数),因此,在将整型数据以字符形式输出时,只取低字节中的数据作为ASCII码字符输出。,#include void main()int x;x=1348;printf(x=%cn,x);,运行结果为:x=D,阅读下列C程序:#include stdio.hvoid main()long x,y,z;x=-0 xffffL;y=-0 xffL;z=-0 xffffffffL;printf(x=%6ld y=%6ld z=%6ldn,x,y,z);x=-0 xffff;y=-0 xff;z=-0 xffffffff;printf(x=%6ld y=%6ld z=%6ldn,x,y,z);,有如下C程序:#include stdio.hvoid main()short int x;unsigned y;long z;x=65535;y=65535;z=65535;printf(x=%dn,x);printf(y=%un,y);printf(z=%ldn,z);,它们在计算机中用二进制表示如下:变量x 1111111111111111变量y 0000000000000000 1111111111111111变量z 0000000000000000 1111111111111111,2.2.4 符号常量,符号常量:为常量起一个名字符号常量声明格式:const 数据类型 常量名=缺省值;,注意:符号常量声明时一定要赋初值,而在程序的中间不能改变其值。,例如:const double PI=3.14159;,float r,area;r=4.5;area=PI*r*r;,内存和地址,计算机内的存储部件,所有指令和数据都保存在内存里速度快,但是掉电即失可以随机访问只要指明要访问的内存单元的地址,就可立即访问到该单元地址是一个无符号整数,其字长一般与主机相同内存中的每个字节都有唯一的一个地址地址按字节编号,按类型分配空间,寻址方式,如何读写内存中的数据?通过变量的地址访问变量所在的存储单元两种寻址方式直接(寻址)访问通过变量地址直接存取变量内容(引用变量的方式是通过变量名,由系统自动完成变量名与其存储地址之间的转换)间接(寻址)访问通过指针变量来间接存取它所指向的变量(它首先将变量的地址存放在一个变量(存放地址的变量成为指针变量)中,然后通过存放变量地址的指针变量来引用变量。),2.2.5 指针与指针变量,1.指针的概念指针是内存单元的地址。一个变量的地址称为该变量的指针。地址运算符&a,表示变量a的地址3000&b,表示变量b的地址4000。,2.2.5 指针与指针变量,2.指针变量用于存放某个内存单元地址的变量。(指向某内存单元的指针)例如:char c=K;char*p=,p(4000),2000,2.2.5 指针与指针变量,(1)指针变量的声明格式:数据类型*变量名;*:声明一个指针类型的变量;数据类型:指针变量所指向的变量的数据类型。,例如:int i;int*p1;float f1;float*p2;,2.2.5 指针与指针变量,(2)指针变量的赋值指针变量的初始化可为地址常量或变量地址,不能是普通整数。可为空NULL(表示不指向任何对象),初始化的一般形式:数据类型*指针名=初始地址值;,赋给指针变量,不是赋给目标变量,例:int i;int*p=,变量必须已说明过类型应一致,例:int*p=,2.2.5 指针与指针变量,例:int i;int*p=,用已初始化指针变量作初值,例:int*p;p=1000;(),例:void main()int i=10;int*p;*p=i;printf(%d,*p);,危险!,例:void main()int i=10,k;int*p;p=,指针变量必须先赋值,再使用,int i,*p;p=,int*p;float*q;p=q;,int i;float*p;p=,int*p;p=100;,判断是真?是假?,指针变量只存放地址!,一个指针变量不能指向与其类型不同的变量!,我是真的,你猜对了吗?,应在类型相同的指针变量之间赋值,2.2.5 指针与指针变量,(3)取内容运算*取指针变量所指的对象变量。格式为:*指针变量,例如:char c,*p=,这里*p 等同于c,例如:float f,*pf=,*pf表示变量f,含义:取变量的地址单目运算符优先级:2结合性:自右向左,含义:取指针所指向变量的内容单目运算符优先级:2结合性:自右向左,两者关系:互为逆运算,&与*操作符,.,.,2000,2008,2012,整型变量i,变量i_pointer,2004,2000,指针变量,10,理解,i_pointer&i&(*i_pointer)i*i_pointer*(&i),=,=,=,=,i_pointer-指针变量,它的内容是地址量*i_pointer-指针的目标变量,它的内容是数据&i_pointer-指针变量占用内存的地址,直接访问与间接访问直接访问:按变量地址存取变量值间接访问:通过存放变量地址的变量去访问变量,例 i=3;-直接访问,3,例*i_pointer=20;-间接访问,20,零指针与空类型指针零指针:(空指针)定义:指针变量值为零表示:int*p=0;,p指向地址为0的单元,系统保证该单元不作它用表示指针变量值没有意义,#define NULL 0int*p=NULL:,p=NULL与未对p赋值不同用途:避免指针变量的非法引用在程序中常作为状态比较,例 int*p;.while(p!=NULL).,void*类型指针表示:void*p;使用时要进行强制类型转换,零指针与空类型指针,例 char*p1;void*p2;p1=(char*)p2;p2=(void*)p1;,表示不指定p是指向哪一种类型数据的指针变量,例:指针的概念,void main()int a;int*pa=,运行结果:a:10*pa:10&a:f86(hex)pa:f86(hex)&pa:f8a(hex),例:输入两个数,并使其从大到小输出,void main()int*p1,*p2,*p,a,b;scanf(%d,%d,5,9,2012,2016,2012,2016,2012,运行结果:a=5,b=9 max=9,min=5,指针与其它类型变量的对比,共性在内存中占据一定大小的存储单元先定义,后使用特殊性 它的内容只能是地址,而不能是数据必须初始化后才能使用,否则指向不确定的存储单元,对该空间进行访问,将可能造成危险可参与的运算:加、减一个整数,自增、自减、关系、赋值只能指向同一基类型的变量,例2-3 常量、变量、指针变量的声明、初始化及使用。,2.3 赋值运算符与赋值表达式,简单赋值运算符符号:=格式:变量标识符=表达式作用:将一个数据(常量或表达式)赋给一个变量,例 a=3;d=func();c=d+2;,2.3 赋值运算符与赋值表达式,复合赋值运算符符号:+=-=*=/=%=&=|=含义:exp1 op=exp2 exp1=exp1 op exp2,2.3 赋值运算符与赋值表达式,说明:结合方向:自右向左左侧必须是变量,不能是常量或表达式赋值转换规则使赋值号右边表达式值自动转换成其左边变量的类型,例 3=x-2*y;a+b=3;,例 float f;int i;i=10;f=i;则 f=10.0,例 int i;i=2.56;/*结果i=2;*/,2.3 赋值运算符与赋值表达式,赋值表达式的值与变量值相等,且可嵌套。,a=b=c=5 a=5+(c=6)a=(b=10)/(c=2),/*表达式值为5,a,b,c值为5*/,/*表达式值11,c=6,a=11*/,/*表达式值5,a=5,b=10,c=2*/,a=12;a+=a-=a*a,/*a=-264等价于a=a+(a=a-(a*a)*/,int a=2;a%=4-1;a+=a*=a-=a*=3;,/*a=0等价于 a=a+(a=a*(a=a-(a=a*3)*/,例:阅读程序,写出结果并演算#include void main()int a=10,b=10;printf(%dt,a+=a-=a*a);printf(%d,b+=b-=b*=b);,举一反三:计算a=3时,a*=4+(a%=2)的结果。,a=5,a=-180 b=0,2.3 赋值运算符与赋值表达式,2.4 算术运算符与算术表达式,表达式:由运算符、操作数(常量、变量、函数调用)和圆括号组成的式子。表达式的书写形式:中缀式:a+b后缀式:ab+前缀式:+ab,例如:int a=1;c=(-a*b+c+67)*56;int b=3;int c=0;,2.4 算术运算符与算术表达式,算术运算符:+-*/%+-加、减、乘、除、求余运算 自加 自减四则混合运算中,先算乘除,后算加减,按从左向右的顺序计算,左结合优先级:-+-*/%-+-(2)(3)(4),常用的标准数学函数,2.4 算术运算符与算术表达式,说明:-可为单目运算符时,右结合性两整数相除,结果为整数%要求两侧均为整型数据,例 5/2=-5/2.0=,例 5%2=-5%2=1%10=5%1=5.5%2=,2,-2.5,1,-1,1,0,(),增一和减一运算符,n+(后缀),n-,(前缀)+n,-n+让参与运算的变量加1,-让参与运算的变量减1作为后缀运算符时,先取n的值,然后加/减1作为前缀运算符时,先加/减1,然后取n的值,增一和减一运算符,n+,n-,+n,-n+让参与运算的变量加1,-让参与运算的变量减1作为后缀运算符时,先取n的值,然后加/减1作为前缀运算符时,先加/减1,然后取n的值,增一和减一运算符,例 i=3;printf(%d,-i+);printf(%d,i);,+-不能用于常量和表达式,如5+,(a+b)+-结合方向:自右向左,-(i+),注意,-3 4,例 int i=3;printf(%d,%d,-i+,i);,-3,3,说明printf函数的输出项扫描顺序是自右向左的。,#include void main()int a=1,b=1;printf(+a=%d,b+=%dn,+a,b+);printf(a=%d,b=%dn,a,b);printf(-a=%d,b-=%dn,-a,b-);printf(a=%d,b=%dn,a,b);,运行结果:+a=2,b+=1a=2,b=2-a=1,b-=2a=1,b=1,2.4 算术运算符与算术表达式,算术表达式指用算术运算符将运算对象连接起来的式子,对于算术表达式要注意以下几个问题:1)注意表达式中各种运算符的运算顺序,必要时应加括号,例如,(a+b)/(c+d)a+b/c+d。2)注意表达式中各运算对象的数据类型,特别是整型相除。C语言规定,两个整型量相除,其结果仍为整型。例如,7/6的值为1;4/7的值为0;(1/2)+(1/2)的值为0,而不是1。,自动类型转换,同种数据类型的运算结果,还是该类型不同种数据类型的运算结果,是两种类型中取值范围更大的那种long double double float long int short char,double,long,unsigned,int,char,short,精度低,精度高,float,自动类型转换,特别需要说明的是,在混合运算过程中,系统所进行的类型转换并不改变原数据的类型,只是在运算过程中将其值变成同类型后再运算。,例 char ch;int i;float f;double d;,ch/i+f*d-(f+i),例:自动类型转换示例#include void main()float x,y;short m;long n;x=3/2+8/3;y=3.0/2+8/3.0;m=1*2*3*4*5*6*7*8*9;n=1l*2*3*4*5*6*7*8*9;printf(x=%f,y=%fnm=%d,n=%ldn,x,y,m,n);,运行结果:x=3.000000,y=4.166667m=-30336,n=362880,自动类型转换,在进行赋值操作时,会发生类型转换将取值范围小的类型转为取值范围大的类型是安全的反之是不安全的如果大类型的值在小类型能容纳的范围之内,则平安无事但是,浮点数转为整数,会丢失小数部分,非四舍五入反之,转换后的结果必然是错误的,具体结果与机器和实现方式有关。避免如此使用,好的编译器会发出警告。,2.5 逗号运算与逗号表达式,分隔符一个变量说明语句可以同时定义多个相同类型的变量,这些变量之间就用逗号来分隔。如:int x,y,z;函数参数表中各参数之间也是用逗号来分隔的。printf(x=%dny=%dnz=%,x,y,z);运算符顺序求值运算符结合性从左向右,2.5 逗号运算与逗号表达式,逗号表达式的格式:表达式1,表达式2,表达式n求解次序:按从左到右的顺序分别计算各子表达式的值逗号表达式的值:等于表达式n的值多数情况下,并不使用整个逗号表达式的值,更常见的情况是要分别得到各表达式的值主要用在循环语句中,同时对多个变量赋初值等 for(i=1,j=10;i j;i+,j-),循环起始条件,循环结束条件,循环增量,例:#include void main()int x,y=7;float z=4;x=(y=y+6,y/z);printf(x=%dn,x);,运行结果:x=3,2.5 逗号运算与逗号表达式,void main()int a=3,b=4,c=1,max,t;if(ab,ac)max=a;else max=0;t=(a+3,b+1,+c);printf(max=%d,t=%dn,max,t);,运行结果:max=3,t=2,2.5 逗号运算与逗号表达式,举一反三:判断输出结果printf(%d,%dn,(3,4,5),(a=3,a=0,a+=2);,运行结果:5,2,2.5 逗号运算与逗号表达式,逗号运算符是所有运算符中级别最低的一种运算符。例如,下面两个表达式的意义是不同的:x=3+4,5+7,10*4 x=(3+4,5+7,10*4)一个逗号表达式又可以与另一个表达式(可以是逗号表达式,也可以不是逗号表达式)连接成新的逗号表达式。(a=2*4,a*5),a-3最后得到整个逗号表达式的值为5。,2.6 运算符的优先级与结合性,表达式的运算次序:取决于表达式中各种运算符的优先级。优先级高的运算符先运算,优先级低的运算符后运算。运算符的结合性:决定了并列的相同运算符的先后执行顺序。语言规定了运算符的优先级和结合性使用圆括号可以提高括在其中的运算的优先级。,2.6 运算符的优先级与结合性,2.6 运算符的优先级与结合性(续),2.7 混合运算时数据类型的转换,当表达式中出现了多种类型数据的混合运算时,需要进行类型转换。隐含转换(自动转换):从占用内存较少的短数据类型转化成占用内存较多的长数据类型时,可以不做显式的类型转换声明。强制类型转换:从较长的数据类型转换成较短的数据类型时,要做强制类型转换。,例如:long lVal=1000;int ival=200;lVal=ival;double d1=123.5f;,基本类型数据占有的内存宽度,2.7 混合运算时数据类型的转换,1.隐含转换(自动类型转换)的规则:,char,short,int,unsigned,long,unsigned long,float,double,低 高,2.7 混合运算时数据类型的转换,2.强制类型转换,消除从大到小的警告 l=(long)i;格式:(类型)表达式 作用:把表达式的值转为任意类型,从而将数据范围宽的数据转换成范围低的数据,但这可能会导致溢出或精度的下降。,例:(int)(x+y)(int)x+y(double)(3/2)(int)3.6用途:满足一些运算对类型的特殊要求,例%,两侧为int(int)2.5%3防止丢失整数除法中的小数部分,例 int x=3,y=2;float f;f=(float)x/y;,2.7 混合运算时数据类型的转换,#include void main()int m=5;printf(m/2=%dn,m/2);printf(float)(m/2)=%fn,(float)(m/2);printf(float)m/2=%fn,(float)m/2);printf(m=%dn,m);,两个整数运算的结果还是整数,不是浮点数,说明:强制转换得到所需类型的中间变量,原变量类型不变,m/2=2(float)(m/2)=2.000000(float)m/2=2.500000m=5,例:void main()float x;int i;x=3.6;i=(int)x;printf(x=%f,i=%d,x,i);,精度损