第三章c++数据类型运算符表达式ppt课件.ppt
常量与变量 整型、实型、字符型数据 变量的初始化 各类数值型数据间的混合运算 算术运算符与算术表达式 赋值运算符与赋值表达式 逗号运算符与逗号表达式,第三章 数据类型、运算符与表达式,数据类型、运算符和表达式的概念,数据类型:数据存在的组织和形式。程序中用到的所有数据都必须指定其数据类型。,运算符:一些具有事先规定的运算功能的特定的符号。这里的运算功能可以是算术运算(加减乘除)、逻辑运算(与或非)或比较运算(大于小于等于),等等。语言共有种运算符。,表达式:按照运算符的性质,用运算符把数据连接起来以 达到数据运算目的而构成的式子。写表达式的最终目的是要进行计算它求出它的值。求解表达式的过程是由计算机完成的,因此,要想得到正确的结果,就必须写出正确的表达式。而一个表达式中往往包含多个运算符,所以必须熟悉每一种运算符的性质(优先级别和结合性),才能写出有正确求解结果的表达式。,3.1 的数据类型,的数据类型,3.2 常量与变量,常量,符号常量:用一个标识符代表一个常量实现方式:使用 #define 预处理命令 宏定义,直接常量:1, 2, 3; 0.1, 10.0; a, 1; “hello”,常变量:C+中,可以使用 const 关键字定义常变量,程序运行期间,值不能被改变的量称为常量,使用符号常量的好处是: 从标识符名可以清楚地看出该常量的含义,做到“见名知意” 在需要修改常量的值时可以做到“一改全改”,容易调整,预处理,编译预处理:是指在对源程序进行正式编译之前所作的一些处理。这些处理是由预处理命令指定的。源程序经过预处理后,再由编译程序进行正式的编译。,#define预处理命令 宏定义 的用法:#define 标识符 字符串它的作用是用预定义标识符去代表一个字符串。在预处理时,源程序中所有在该#define命令后出现的该标识符全部用指定的字符串代替。,预处理命令是由 规定的,但它不是语言本身的组成部分,不能直接对它进行编译。预处理命令都是以符号“”开头的。,#include “stdio.h”#define PI 3.14159int main() float r, c, s, v; r=20; c=2*PI*r; printf(“周长=%f”, c); s=PI*r*r; printf(“面积=%f”, s); v=4*PI*r *r *r/3; printf(“体积=%f”, v); return(0);,符号常量的实现,这个字符串将要在预处理时去替换符号PI,标识符名:PI编译预处理时,这一行以后的源程序中出现的PI都会被指定的字符串代替。,预处理后进行正式编译,替换进去的3.14159就会被理解为是一个实数。,#include “stdio.h”#define PI 3.14159int main() float r, c, s, v; r=20; c=2*PI*r; PI = 100; return(0);,使用符号常量的注意事项,错误,注意1:符号常量不是变量,不能被赋值。,#include “stdio.h”#define PI 3.14159int main() float r, c, s, v; r=20; c=2*PI*r; printf(“PI = %fn”, PI); return(0);,使用符号常量的注意事项,不替换,注意2:如果指定的符号出现在双引号中,则不被替换。,要替换,#include “stdio.h”const PI = 3.14159;int main() float r, c, s, v; r=20; c=2*PI*r; printf(“周长=%f”, c); s=PI*r*r; printf(“面积=%f”, s); v=4*PI*r *r *r/3; printf(“体积=%f”, v); return(0);,常变量,const关键字的用法:const 标识符 常量值,常变量名:PI,常变量必须初始化,在定义的同时给以值,同样要注意的是:虽然PI是变量,但是它是用 const 关键字定义的常变量,所以也不能被赋值。,PI=100;,变量,允许把值存放在变量中,每个变量都由一个变量名来标识。,程序运行期间,值可以被改变的量称为变量,每个变量都必须有一个变量类型。,每个变量根据它的类型不同,在内存中占据一定数目的字节单元,该变量的值就存放在这些内存单元中。,123,prod,变量名 prod 实际上是一个符号地址,变量prod 所占据的内存单元,123是变量prod的变量值,内存单元的地址,内存单元的内容,在对程序编译时由系统给每一个变量按其类型分配内存单元,同时,系统内部维护着变量名和它的内存单元地址的对应信息。,变量就是命名的内存单元,变量的命名规定,合法的变量名:area, sum, answer, month, name, Name, Step1, step2, number_of_student, average_score, _class1,语言中,变量(用户标识符)的命名规定:,只能由字母,数字,下划线组成; 开头的第一个字符只能是大小写字母或下划线; 大小写是敏感的; 不能与的关键字重复; 名字在整个程序中必须是唯一的; 名字的长度不能超过系统的规定。,非法的变量名:3rd_entry (数字开头) all$done(包含非法字符$) the end (包含空格)int(系统关键字),避免使用无意义的名字,应尽量做到“见名知意”; 尽量使用代表变量实际含义的英文单词或缩写作标识符名; 当名字包含多个单词时,通常使每个单词的首字母大写; 以下划线开头的名字通常是系统内部保留的标识符名; 在整个程序中保持统一的命名方式。,变量的命名习惯,语言中,变量(标识符)的命名习惯:,好的变量名:CircleArea, TotalScore, UserSelection, choice, StudentNumber, AverageScore, SampleFrequency,不是很好的变量名:a, aa (不知何意)numberofstudent (全部小写难以辨认)totaltotals (名字太相似),变量的定义和使用,变量定义具有三个目的: 定义变量名; 定义变量类型; 向程序员描述该变量。,语言中,变量必须“先定义,后使用”,int radius; /* the radius of circle */,关键字 int 告诉编译系统我要定义一个整型变量,用它来保存一个整型的数值。,这是变量的名字。以后的程序中就用这个名字来访问这个变量。,注释用来解释这个变量,它是给程序员的信息。对程序主要的变量作注释是很好的习惯。,#include int main() int a , b , sum ; a=123; b=456; sum=a+b; printf(“sum=%dn”, sim); return(0);,变量的定义和使用,变量“先定义,后使用”的好处是:,只允许使用定义过的变量。凡是未被事先定义的符号,不作为变量名。这样可以检查出程序中错误使用的变量名。,此处定义的变量名是 sum 。,此处由于输入错误或其它原因,出现了名字为 sim 的符号。由于该符号在这之前从未定义过,所以在编译时,便会出现错误信息。,Error:Undefined symbol sim,#include int main() int a, remainder; float c; a=23; c=2.5; remainder= ac ; printf(“余数=%dn”, remainder); return(0);,变量的定义和使用,变量“先定义,后使用”的好处是:,定义变量时指明了变量的类型,这样在对源程序进行编译时,可以就此类型检查该变量所参与的运算是否合法。,变量a是整型的,这个表达式中的符号是“求余”运算符,它要求参与运算的数据必须是整型的。此处变量 a是整型,而变量 c 却是实型的,所以编译时就会出现错误信息。,Error:Illegal use of floating point,变量c是实型的,变量的定义和使用,int age; /* the age of student */float score; /* the score of student */float average; /* the average of score */long number; /* the number of student */double distance; /* between earth /* key user hit */,变量定义的一般格式是:type name; /*comment */类型 名字; /* 注释 */,系统将根据变量的定义为其分配相应大小的内存单元。,3.3 整型数据,整型常量 整型变量 整型数据在内存中的存储方式,整型常量,十进制整型常量:数码09,符号(负号)构成 如 123, -456, 0,八进制整型常量:以数字“0”开头,数码07,符号(负号)构成 如 0123, 即(0123)8 ,等于(83)10 -011, 即(-011)8 ,等于(-9)10八进制整型常量中不应出现“7”以上的数码。如 0128, 0209 都是非法的八进制整型常量。,整型常量即整常数。中有下面三种形式的整型常量:,十六进制整型常量:以 数字“0”字母”x”-“0 x”开头,数码09,字符af(AF),符号(负号)构成 如 0 xFF, 即(0 xFF)16 ,等于(255)10 -0 x11, 即(-0 x11)16 ,等于(-17)10 十六进制整型常量中不应出现“F”以上的数码。C语言中没有二进制整型常量,用十六进制整型常量表示二进制整数,整型变量的分类,注:有符号整型变量中,关键字signed可以省略。,整型数据在内存中的存储方式,数据在内存中是以“二进制数”的形式存放的。,数据在内存中是以“二进制数的补码”形式存放的。,例如:int a=10; 那么内存中实际存放的是 10 的补码,如果是:int a=-10; 那么内存中实际存放的是 -10 的补码,-10 的原码是:,最高位不动,其余各位取反:,整个数加上1:,求-10补码的方法:,对于有符号变量:把最高位作为符号位保存数据的符号(0为正,1为负),其余位保存具体数值,因此可以用于正确保存限值范围内的正数或负数。,有符号和无符号的区别, 有符号和无符号的区别是什么?,关键在于“最高位”的性质。,如果有:int a; 那么a的有效数值范围为 -3276832767,有符号整型变量 a=32767:,如果有:unsigned int b; 那么b的有效数值范围为 065535,最高位代表符号,对于无符号变量:最高位不作为符号位,全部的位都用来保存数据的数值,因此可以用于正确保存限值范围内的正数。,无符号整型变量 b=65535:,最高位代表数值,整型数据的表示范围,由于每一种整型数据占有的字节单元数目都是有限的,所以每一种整型数据可表示的数的范围也是有限的。,由于不同类型的整型数据占有的字节单元数目是不同的,所以不同类型的整型数据可表示的数的范围也是不同的。,整型变量的定义,变量的定义一般放在函数体的开头部分。,定义方法:类型符 变量名列表; (用逗号分隔),如: int num;unsigned int age,score; long distant,SampleTimes;,#include int main() int max, over; max=32767; over=max+1; printf(“max=%d, over=%d”, max,over); return(0);,整型变量的溢出, 由于每一种整型数据可表示的数的范围都是有限的,所以在使用整型变量时要特别注意“数据溢出”的问题。, int型的有效表示范围是 -32768 +32767 。,max是:,max+1over是:,32767,-32768,数据溢出了!,将变量over定义成long型就能得到正确的结果。,3.4 实型数据,实型常量 实型变量 实型数据在内存中的存储方式,实型常量,十进制小数形式:由数字和小数点组成。(小数点必须有)如 10.23, -0.456, 78.0, 0.0, 89.,指数形式:s E n 或 s e n 形式。注意: E或e前面必须有数字,后面的指数必须为整数。如 218.3=218.3E0=2183E-1=0.02183E+4,实数又叫“浮点数”。实数常量有两种表示形式:,指数形式的实型常量,有“规范化指数形式” ,即在字母E或e之前的小数部分中,小数点左边必须有且只有一位非零的数字。如 218.3=2.183E+2 ; 0.00218.3=2.183E-3程序以指数形式输出实数,就是以“规范化指数形式”输出,实型数据在内存中的存储方式,实型数据在内存中是以“尾数”和“阶码”的形式存放的。,在一个实型数据(浮点数)所占字节单元中,一部分位用来保存阶码,一部分位用来保存尾数。,不同的编译系统位数分配不同。总之,尾数部分位数越多,可以表示的数的有效数字位数就越多,精度就越高;阶码部分位数越多,可以表示的数的范围就越大。,实型变量的分类,由于不同的实型数据是用不同数目的有限字节单元保存的,所以它们能表示的数值范围是不同的,能保留的有效数字位数也是不同而且是有限的。,实型变量的定义,变量的定义一般放在函数体的开头部分。,定义方法:类型符 变量名列表; (用逗号分隔),如: float SinValue, CosValue;double area,result;,注:语言中的所有关键字都是小写的。,实型变量的精度有效数字位数例:floata,b;a=12345674.;b=12345670.;问:ab?,3.5 字符型数据,字符常量 字符变量 字符型数据在内存中的存储方式 字符串常量,字符型常量,比如: a , A , d , D ,? , % , $ , 2 , 4,注意: a 和 A , d 和 D 都是不同的字符常量。,的字符常量是用单引号 括起来的一个字符。,另外:语言还存在另一种形式的特殊的字符常量。,它是用单引号括起来的以一个 字符开头的规定的字符序列。,以开头的字符叫反斜杠字符。这种特殊的字符常量称为“转义字符”。,注意: 开头后随1-3个规定字符数字是一个字符,转义字符常量及其含义,注意表示字符的转义16进制数与十六进制整型常量写法不同 x 0 x,字符型变量,字符型变量用来存储字符型常量。一个字符变量只能保存一个字符。,如 char InputKey, UserSelection; unsigned char lines, grade;,定义方法:类型符 变量名列表; (用逗号分隔),字符型数据在内存中的存储方式,每个字符型数据在内存中只占一个字节,该字节中实际保存的是该字符的代码。,ASCII (美国信息交换标准代码)American Standard Code for Information Interchange,ASCII 代码实际上是一个0255之间的整数。每一个整数对应着一个不同的字符,即每一个字符都有一个不同的整数代码。对字符型数据来讲,它的那一个字节中保存的就是这个整数。,常用字符及对应ASCII码,常用字符及对应ASCII码,可见,字符型数据存储对应的 ASCII 码,而 ASCII 码是一个整数,按整型数据的存储方式存储,因此在语言中两者的存储方式是类似的,从而在一定范围内可以通用,即两种类型的数据可以相互赋值,相互输出,也可以在一起进行运算。,字符型数据在内存中的存储方式,“一定范围内” 指的是“一个字节”所能保存的整数范围内。有符号型整数:-128127 无符号型整数:0255,65,这个字节存储的内容是01000001。如果它是一个整型数据,那就是整数65;如果它是一个字符型数据,那就是字符A。,ASCII 值65,#include int main( ) char c1, c2; int n1, n2; c1 = b; c2 = 97; n1 = 98; n2 = a; printf(“c1 = %c, c2 = %cn”, c1, c2); printf(“n1 = %d, n2 = %dn”, n1, n2); printf(“c1 = %d, c2 = %dn”, c1, c2); printf(“n1 = %c, n2 = %cn”, n1, n2); return(0);,整型数据和字符型数据通用:例,既可以把整型数据赋值给字符型变量。,也可以把字符型数据赋值给整型变量。,既可以把字符型数据按整数形式输出。(%d 整型格式符),也可以把整型数据按字符形式输出。(%c 字符型格式符),#include int main( ) char c1, c2, c3; c1 = A; c2 = b; c3 = ; c1 = c1 + 32; c2 = c2 c3; printf(“c1 = %c, c1 = %dn”, c1, c1); printf(“c2 = %c, c2 = %dn”, c2, c2); return(0);,整型数据和字符型数据通用:例,字符数据可以和整型数据一起进行算术运算。,字符型数据之间也可以进行算术运算。,既可以把字符型数据按字符形式%c输出,也可以把字符型数据按整数形式%d输出。,实际上都是整数之间的算术运算。,运行结果:c1=a, c1=97 c2=B, c2=66,空格的ASCII码=32,字符串常量,比如: “a”, “”, “Hello,worldn”, “9811113”, “ABC”,”101102103”,?,的字符串常量是用双引号“”括起来的若干个字符。,字符串常量在内存中占用连续的字节单元,每个字符按顺序占一个字节。,语言规定:自动在每一个字符串常量的结尾加一个“字符串结束标志字符”,以便系统据此判断字符串是否结束。,一个字符串常量中包含的字符个数是不确定的。那么,系统在处理字符串常量时如何知道何处结束呢?,字符串结束标志字符, 0 是ASCII码为0的字符,即位于字符表中的第一个NUL字符。它是一个“空操作字符”,就是说,它既不引起任何控制动作,也不产生任何显示。,的字符串结束标志字符是 0 。, 因此,的字符串常量在内存中占用的字节数等于可见字符数加上1,即结束标志字符占用的一个字节。,“HELLO”,字符串结束标志字符也是一个字符,也要占用一个字节。,总共占用6个字节,5个可见字符,A和“A”的区别, 由于语言对每一个字符串常量均在其末尾自动添加一个字符串结束标志字符0,因此: A 占一个字节单元 “A” 占两个字节单元, 包括 A 和 0 两个字符,不能把一个字符串常量赋值给一个字符变量。如 char c1 = “A” ; 是错误的。,?,为什么是错误的。,原因1:“A” 占两个字节单元,而字符变量c1只有一个字节,所以无法赋值;,原因2:真正的原因。语言实际上把字符串处理成字符指针,把一个指针赋值给一个字符变量当然是错误的。,课堂练习, 问题3:1 和 1 是否相同?为什么?, 问题4:10 和 1 是否相同?为什么?,答案:(B),答案: (B),答案:不相同。因为前者是整数1,它的值是1,而后者是字符 1 ,它的值是49(ASCII码)。,答案:相同。因为字符 0 的值是48,加1等于49 ,正好是字符 1 的值。,3.6 变量赋初值, 当一次定义多个变量时,不能用连续号的方式对多个变量进行初始化,变量赋初值,一个变量在定义之后,第一次赋值之前,它的值是不确定的。在赋初值前,不能让其参与运算,否则会得到不可预知的结果。对变量进行定义的同时给变量赋初值,称为 初始化,, 在定义变量的同时进行初始化除static,extern 变量外,初始化与定义,赋值等价, 当一次定义多个变量时,可以对其全部或部分进行初始化,如:int TotalStudent=40;等价于:int TotalStudent; TotalStudent=40;,如:int TotalStudent=40, TotalScore=0, average;,如:int TotalScore=AverScore=0; 是错误的。,正确的应该是:int TotalScore=0, AverScore=0;,3.7 各类数值型数据间的混合运算,各类数值型数据间的混合运算,不同类型的数值型数据之间可以进行混合运算,即是说,各种整型数据、实型数据和字符型数据可以在一起构成表达式。如:10+a+1.5*123.45*B,系统在求解包含混合运算的表达式时,先把不同类型的数据转换成同一类型,然后进行运算。转换规则如图:,横向向左的箭头表示必定的转换。比如,char型数据必定先转换成int型,float型必定会转换成double型。,纵向向上的箭头表示当有这些不同类型数据混合运算可能进行的转换。,各类数值型数据间的混合运算:例,注意:两个整数运算,表达式的值一定是整数。,#include int main( ) int a=3, b=5, c=0; c = a/b; printf(“c=%dn”, c); c = b/a; printf(“c=%dn”, c); return(0);,两个整型变量a和b运算的结果肯定是整数,所以 a/b这个除法表达式的值是 3/5 ,等于0 。,同样a/b运算的结果也肯定是整数,所以这个除法表达式的值是 5/3 ,等于1 。,#include int main( ) unsigned int d=1, e=2; if ( d - e 0 ) printf(“den”); else printf(“den”); return(0);,各类数值型数据间的混合运算:例,此处是由两个无符号整型变量d和e构成的减法表达式d-e,其表达式的值一定是正数,不会等于负数。所以,当进行d-e是否0的判断时,得到的结论就是Yes ,从而输出“de”,而实际上d并不大于e。,注意:两个无符号数运算/无符号数与有符号数运算,表达式的值是无符号数 ,是正数。,#include int main( ) unsigned int d=0; int e=-1; if ( d+e 0 ) printf(“d+e0n”); else printf(“d+e0n”); return(0);,3.8 算术运算符和算术表达式,优先级别和结合性的概念基本的算术运算符强制类型转换运算符 自增、自减运算符,优先级和结合性的概念,优先级:运算符的优先级高,先运算。,结合性:相同优先级的运算符,按照结合性规定的次序运算。,参考课本p375p376的附录语言全部34种运算符的性质以及优先级和结合性。,优先级 1+2*3 不是1加2然后乘3 (9),而是1加上2乘3的结果(7)结合性 3*2%6 不是3乘以2模6除的结果(6) 而是3乘2的结果模6除(0)-a+-,+是相同优先级的运算符,右结合性,运算次序应为-(a+) ?: 条件运算符,12?3:4, 得4. 12?3:45?6:7 右结合性,运算次序 12?3:(45?6:7),( ) - .! + - - (type) * & sizeof * / %+ - = !=&|&|? := += -= *= /= %= = = &= = |=,未标水平箭头左结合,赋值,条件,算术, 类型长度,自增减,求负运算符 逻辑,关系运算符 求地址,地址上内容运算符 位运算符 逗号,强制,括号,下标,成员,指向成员运算符,! 逻辑非:逻辑值2个真,假.非真即假,非假即真.用数值1表示真,用数值0表示假!0=1,!1=0 a等于多少?,算术运算符和算术表达式,算术运算符(双目): 加 减 * 乘 / 除 求余,算术表达式:用上述算术运算符按规定把运算量连接起来构成的式子就是算术表达式。其中,参与求余运算的运算量必须是整型数据类型。如:20*4 ; 10-3+5*2-8%9/3 ; 3%5,算术运算符的优先级:,算术运算符的结合性:,自左向右,为了保证写出的含有多个不同运算符的表达式能计算出正确的结果,就必须掌握每种运算符的优先级和结合性。,(按各种运算符的结合性),优先级和结合性的概念,(按各种运算符的优先级),10 - 3 + 5 * 2 - 8 % 9 / 3,10 - 3 + ( 5 * 2 ) ( 8 % 9 / 3 ),10 - 3 + ( 5 * 2 ) ( (8 % 9 ) / 3 )10 - 3 + 10 (8 / 3)(10 - 3 )+ 10) 215,强制类型转换运算符和表达式,强制类型转换运算符(单目)运算符: (类型名) 用法: (类型名) (变量或表达式)优先级: 高于算术运算符结合性: 右结合性,用途: 满足某些运算符的规定(比如求余运算符) 确保函数调用时实参与形参的类型一致,如:(long)(length-200),如:(float)5/3,如:(int)x%(int)y,相当于:(float)5)/3,相当于:(int)x)% (int)y),#include int main( ) float a = 3.5, b = 2.3; int c; c = (int) a - (int) b ; printf(“c=%dn”, c); c = (int) a % c ; printf(“c=%dn”, c); return(0);,强制类型转换运算符和表达式:例,由于强制类型转换运算符的优先级高于算术运算符,所以就相当于: (int) a)-(int) b),参与求余运算的运算量必须是整型,所以此处须进行强制类型转换。所以就相当于: (int) a) c,注意:参与强制类型转换的变量本身的类型并不会改变。,自增、自减运算符,自增、自减运算符(单目)运算符: 自增 自减 优先级: 高于算术运算符,和强制类型转换运算符同级结合性: 右结合性作 用: 使变量的值加或减,用法: + 变量 - 变量 (运算符前置用法) 变量 + 变量 - (运算符后置用法),运算符前置时: 变量先加(减),后被使用(参与其它运算) + i - i,?,两种用法的区别在哪?,运算符后置时: 变量先被使用(参与其它运算) ,后加(减) i + i -,先用后加(减),是指先用未自增减的变量,参与表达式计算/作为参数参与函数调用,它们有结果后,再对变量自增减,不影响前面的结果,#include int main( ) int a = 5, m ; m = + a ; printf(a=%d, m=%dn, a, m); m = a - - ; printf(a=%d, m=%dn, a, m); + a ; m - - ; printf(a=%d, m=%dn, a, m); printf(a=%d, m=%dn, a - -, + m );,自增、自减运算符:例,由于运算符前置,所以变量a先加1,然后再被使用。此处的使用是参与赋值运算,所以再把加过1的变量a赋值给变量m 。整个过程相当于顺序执行以下两个语句:a=a+1; m=a;,由于运算符后置,所以先使用,即把a赋值给m ,然后再加。整个过程相当于顺序执行以下两个语句:m=a; a=a-1;,这两个表达式是单一的自增自减表达式,没有其它的运算,所以其作用只是将变量加或减。,这个地方的两个自增自减表达式也要被使用:去参与输出操作。所以同样存在着先加减还是先使用的问题。,#include int main( ) int a = 5, m ; m = + a ; printf(a=%d, m=%dn, a, m); m = a - - ; printf(a=%d, m=%dn, a, m); + a ; m - - ; printf(a=%d, m=%dn, a, m); printf(a=%d, m=%dn, a - -, + m ); return(0);,a=6, m=6,a=5, m=6,a=6, m=5,a=6, m=6,运行结果:,自增、自减运算符的注意事项,用途:常用于循环结构中循环变量的自动增减 常用于指针变量的自动增减,使其指向相邻的内存单元,?,为什么?,注意:自增、自减运算符的运算量只能是变量,不可能是常量或表达式。,因为自增、自减运算符实际上具有赋值功能,是语言中除了赋值运算符之外唯一具有改变变量值的功能的运算符。,+ i,相当于,i = i + 1,- - i,相当于,i = i - 1,而被赋值的量只能是变量,常量和表达式不可能被赋值。,+ 10 (x+y) +,与自增、自减运算符相同优先级的有 ! - ()* & sizeof(逻辑非,按位反,负,强制,地址内容,取地址,类型长度)结合性是从右到左 int i=0; -i+ ; 运算次序是 -(i+)。由于i+是先用后加,所以表达式是用i的未修改值求负,值为0,然后 i 值加1,得1。 后置自增减运算符的“使用,增减”特性,并不改变其结合性,仍然是:-i+ 是i先自增,再求负 -(i+) 右结合。 而不是i先求负,再自增 (-i)+ 左结合,错,表达式-i是不能够+的。后置自增减运算符,在满足结合性前提下使用后置特性,后置特性主导求值次序,3.9 赋值运算符和赋值表达式,赋值运算符 赋值表达式,赋值运算符,赋值运算符(双目)运算符: 优先级: 只比逗号运算符级别高,位于整个运算符优先级表的 倒数第二位;低于算术运算符。结合性: 右结合性作 用: 将一个数据赋给变量,如:num=40 常量40赋值给变量num,如:aver=total/num 表达式total/num的值赋给aver,如:temp=aver 变量aver的值赋给temp,复合赋值运算符,复合赋值运算符(双目)在原有的赋值运算符之前再加上其它运算符,即构成复合赋值运算符。其它运算符包括5种算术运算符和5种位运算符。运算符: += -= *= /= %= &= = |= =,a+=3,相当于,a=a+3,x%=y+8,相当于,x%=(y+8),x=x%(y+8),不相当于,x= x%y+8,例:int a=10,b=3,c=8;c=b+=a-=4;问a,b,c的值 a=6,b=9,c=0,赋值表达式,用赋值运算符把一个变量和一个表达式连接起来的式子。一般形式: 变量表达式,如:num=40 常量40赋值给变量num,如:aver=total/num 表达式total/num的值赋给aver,如:temp=aver 变量aver的值赋给temp,注意:赋值表达式的左边只能是变量,而右边可以是常量、变量或任何合法的表达式。,10=x x+y=1,赋值表达式求解过程,赋值表达式的求解过程:先求解赋值运算符右边的表达式,再将该表达式的值赋给左边的变量。最后,整个赋值表达式的值就等于被赋值后的左边变量的值。可见,求解赋值表达式值的过程,伴随着给变量赋值的作用。我们写一个赋值表达式,系统会求解它并得到一个值。而我们的目的通常都是为了给一个变量赋值(这个目的是在系统求解赋值表达式的过程当中实现的),因此往往并不关心最后求出的赋值表达式的值(就是说,不会去使用这个值)。由于赋值运算符是“右结合性”,所以多个赋值表达式连写时,是从右到左依次赋值 A=B=C=D=1相当于D=1, C=(D=1),C=1 B=(C=1),B=1 A=(B=1) A=1,1,1,1,赋值表达式求解过程,由于赋值运算符的级 别只比逗号运算符高,x = - 4/ (2 * 2 ),x = (- 4/ (2 * 2 ) ),x = - 1,为了求解整个赋值表达式的值,先求解号右边的表达式的值,再把求解出的号右边的表达 式的值赋给号左边的变量,最后,原来的赋值表达式的值就等于被赋值后的变量的值,x = - 4 / (2 *2 ),- 1,赋值表达式的值就等于,x,#include void main( ) int a, b, c, d; /* int a = b = c = 10; */ a = b = c = 10; printf(“a=%d, b=%d, c=%dn”, a, b, c); d = ( a = 3 ) * ( b = b + 1 ) = c ; d = ( a = 3 ) * ( b = b + 1 ) c ; printf(“a=%d, b = %d, c=%d, d=%d n”, a, b, c, d);,赋值表达式:例,是错误的。因为当一次定义多个变量时,不能用连续号的方式给多个变量赋同一初值.,是正确的。因为这是一个赋值表达式。因式分解的结果就相当于: a = ( b = ( c = 10 ) ),是错误的。因为=号左边只能是变量。,是正确的。,赋值时的类型转换,如果赋值运算符两边的运算量类型不一致,但都是数值型或字符型的数据时,在赋值时系统自动进行类型转换。,float 赋值给 int 型变量,舍弃实型数据的小数部分int 型赋值给 float 型变量,数值不变,以浮点形式存储3. char 赋值给 int 型变量,将 一个字节的 char 数据放到 int 型数据的低字节,如果char 数据最高位为1, int 型数据的高位字节位置1(符号扩展),如果char 数据最高位为0, int 型数据的高位字节位置0 ; int赋值给char 变量,int 数据的低字节直接存进 char 变量中4. 不同类型的整型数据之间的赋值:直接按存储单元的存储形式传送,3.10 逗号运算符和逗号表达式,逗号运算符 逗号表达式,逗号运算符和表达式,逗号运算符(多目)运算符: , 用 法: 表达式1,表达式2,表达式3,表达式n优先级: 整个运算符优先级表中最低的结合性: 自左向右作 用: 用逗号把若干个合法的表达式连接起来形成一个表 达式,让系统依次求解,逗号表达式:用逗号运算符把若干个合法的C表达式连接起来形成的一个式子。如: i=1, j=1, sum=0如: x+y, 10, z=x%y, z,从广义上讲,常量和变量也可以认为是表达式。,逗号表达式的求解过程,逗号表达式的求解过程逗号运算符又称“顺序求解运算符” ,即对于一个逗号表达式,其求解过程是:先从左到右依次求解用逗号连接的每个表达式,而整个逗号表达式的值就等于最后那个表达式的值。,逗号表达式的用途从上述求解逗号表达式的过程可以看出,为了求出整个逗号表达式的值,必须先依次求出逗号表达式中每个表达式的值,因此,写逗号表达式的目的往往不是为了整个表达式的值,而是利用求解逗号表达式的过程来求解其中每个表达式。,i=1, j=1, sum=0,逗号表达式:由3个赋值表达式构成,1, 1, 0,依次求解3个赋值表达式的值,0,逗号表达式的值是最后那个赋值表达式的值。这个值往往不被使用。,#include void main( ) int x, b; x = 0, b = 0 ; x = ( b = 3, 2 * b ); printf(“x=%d, b=%dn”, x, b); x = b = 3, 2 * b ; printf(“x=%d, b=%dn”, x, b);,逗号表达式:例,是逗号表达式。求解它就要依次求解两个赋值表达式,而求解赋值表达式的过程又具有给变量赋值的作用,所以这个逗号表达式的作用就如同表达式 x=b=0 一样,但是两者本质是不一样的。,是赋值表达式。,是逗号表达式。,x=6, b=3,x=3, b=3,运行结果:,课堂练习, 1. 以下各组标识符中,全部是合法C标识符的是( ),(A) string,sum,Double,_1st(B) D56,bStatus,strTemp,HighLimit(C) name,float,month,stu_n1(D) class1,day,string_1,Score.1,答案:(B) (D), 2. 以下字符中,( )是非法的C转义字符,(A) t (B) 018(C) n(D) 0 x