《C语言程序设计基础与实训教程》第2章:数据类型、运算符和表达式.ppt_第1页
《C语言程序设计基础与实训教程》第2章:数据类型、运算符和表达式.ppt_第2页
《C语言程序设计基础与实训教程》第2章:数据类型、运算符和表达式.ppt_第3页
《C语言程序设计基础与实训教程》第2章:数据类型、运算符和表达式.ppt_第4页
《C语言程序设计基础与实训教程》第2章:数据类型、运算符和表达式.ppt_第5页
已阅读5页,还剩102页未读 继续免费阅读

下载本文档

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

文档简介

第2章 数据类型、运算符和表达式,(时间:3次课,6学时),学习目的与要求: 本章是包括C语言的数据类型、运算符和表达式, 是C语言程序设计最基础的部分。通过这一章的学习,使学生了解C语言的数据类型,掌握各种数据类型所占的字节数、使用方法、类型的自动转换和强制转换,标志符的使用规则;掌握各种常量的使用,变量的基本概念及定义、初始化和在内存中的存储形式;掌握算术运算符的使用,运算符的使用规则、优先级和结合性等。,第2章 数据类型、运算符和表达式,第2章 数据类型、运算符和表达式,2.1 C的数据类型 2.2 常量 2.2.1 整型常量 2.2.2 实型常量 2.2.3 字符型常量和符号常量 2.2.4 符号常量 2.3 变量 2.3.1 变量概述、标志符 2.3.2 整型变量 2.3.3 实型变量 2.3.4 字符变量 2.3.4 变量赋初值 2.3.5 不同类型数据间的相互转换 2.3.6 数值的定点表示形式与浮点表示形式,2.4 运算符和表达式 2.4.1 C运算符简介 2.4.2 算术运算符和算术表达式 2.4.3 赋值运算符和赋值表达式 2.4.4 逗号运算符和逗号表达式 2.5 上机实训 2.6 习题,第2章 数据类型、运算符和表达式,2.1 C的数据类型,在第一章中,我们已经看到程序中使用的各种变量都应预先加以定义,即先定义,后使用。对变量的定义可以包括三个方面: 数据类型 存储类型 作用域,在本章中,我们只介绍数据类型的说明。其它说明在以后各章会陆续介绍。所谓数据类型是按被定义变量的性质、表示形式、占据存储空间的多少和构造特点来划分的。在语言中,数据类型可分为:基本数据类型,构造数据类型,指针类型,空类型四大类。见图2-1。,图2-1 C语言的数据类型,1、基本数据类型:基本数据类型最主要的特点是,其值不可以再分解为其它类型。他包括整型、字符型、实型(分为单精度型和双精度型)和枚举类型四种。 2、 构造数据类型:构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。在C语言中,构造类型有以下几种: 数组类型 结构体类型 共用体(联合)类型,3 指针类型:指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个变量在内存储器中的地址。 4 空类型:空类型void只能申明函数的返回值类型,不能申明变量。在调用函数值时,通常应向调用者返回某种类型的一个函数值,如果不需要有函数返回值,则在函数定义前面加上void表示空类型。在后面函数中还要详细介绍。 在本章中,我们主要介绍基本数据类型中的整型、浮点型和字符型。其余各种类型以后分别有章节介绍。,2.2 常量,在程序运行过程中,其值不能改变的量称为常量。如我们在数学里面的123,0,45为整型常量,2.8,-0.56等称为实型常量,在C语言里,还有一种经常用到的常量如a, x等称为字符常量,“abc“,“123“等称为字符串常量。下面就各种常量作一些介绍。,2.2.1 整型常量,C语言里面整型常量可以用十进制、八进制和十六进制三种形式表示。 1 、十进制常量:由数字19开头其余各位由09组成,各数字间不允许有空格符及其他字符。如123,0等。十进制里还有一种常量叫长整型常量,占4个字节。一般在十进制常量后加上L(或l)就变成长整型常量。如123L。 2、 八进制常量:以0开头,其它位由数字07组成。如0123等。 3、 十六进制常量:以0x或0X开头,其它位由数字09或字母af(或AF,大小写意思相同)组成。如0x123a,0Xabc等。,2.2.2 实型常量,实数(real number)又称浮点数( floating-point number),他有两种表示形式: 1、 十进制小数形式。由数字和一个小数点组成,且小数点不可缺少。如:3.12、.123、123.、0.0等均是合法形式。注意:小数点前面或后面没有数字也是合法的形式。,2、 指数形式。任何一个合法的指数形式的实型常量从左往右都是由数字,字母e(或E)和指数三部分组成。如:45.3e5、-231.23E12、-0.12e-2、12e0等均是合法形式。 注意:用指数形式表示实数时,e前必须有数字(如e3错误,系统会将其视为一个变量),e后面的指数必须是整数。,一个实数可以有多种指数的表示形式,我们只要在改变小数点位置时相应的改变指数的值即可。如231.23E12还可以写成23.123E13、2312.3E11、2.3123E14、0.23123E15等等,这样就容易造成用户和系统处理数据的不便,所以C语言有一个“规范化指数形式”的概念,这种形式规定在字母e(或E)前的小数部分中,小数点左边应有一位(且只能有一位)非零的数字。如前面几个例子中,只有2.3123E14是规范化指数形式,其他的都不是。一个实数在使用指数形式输出时,是采用规范化指数形式输出的。 实型常数不分单、双精度,都按双精度double型处理。当然,如果想使用float型的实型常量,可以在此实数后加F(或f)表示;同理,实数后加L(或l)表示它是long double类型。,2.2.3 字符型常量和字符串常量,一、字符常量和转义字符 C的字符常量是用单引号括起来的一个字符。如a, z, R, #,n等都是字符常量。一个字符常量中只能存放一个字符。注意,字符可以是字符集中任意字符,R和r是不同的字符常量。数字被定义为字符型之后就不能参与数值运算。如3和3 是不同的。3是字符常量,不能当成数字3参与运算。,在字符常量里面,有一种以反斜线“开头、后跟一个或几个字符的特殊字符常量,称为转义字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。例如,在前面各例题printf函数的格式串中用到的n就是一个转义字符,其意义是“回车换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。以下是常用转义字符表。,转义字符 转义字符的意义 ASCII代码 n 回车换行 10 t 横向跳到下一制表位置 9 b 退格 8 r 回车 13 f 走纸换页 12 反斜线符() 92 单引号符 39 双引号符 34 a 响铃 7 ooo 13位八进制数所代表的字符 xhh 12位十六进制数所代表的字符 表2-1 常用的转义字符及其含义,在C程序中使用转义字符 d d d或者 x h h可以方便灵活地表示任意字符。 d d d为斜杠后面跟三位八进制数,该三位八进制数的值即为对应的八进制A S C I I码值。 x后面跟两位十六进制数,该两位十六进制数为对应字符的十六进制A S C I I码值。例如012 (十进制ASCII码为10)代表“换行”, 0或000代表ASCII为0的控制字符,即“空操作字符”,它将用在字符串中。,使用转义字符时需要注意以下问题: 1) 转义字符中只能使用小写字母,每个转义字符只能看作一个字符。 2) 在C程序中,使用不可打印字符时,通常用转义字符表示。 见【例2.1】,【例2.1】转义字符的使用。 main() printf(“ ab ctderfn“); printf(“hijktLbMn“); 运行结果如下: f ab c de hijk M,二、字符串常量,字符串常量是由一对双引号括起来的字符序列。例如: “CHINA“ , “welcome!“ , “123“ 等都是合法的字符串常量。 字符串常量和字符常量是不同的量。它们之间主要有以下区别: 1) 字符常量由单引号括起来,字符串常量由双引号括起来。 字符常量只能是单个字符,只占一个字节,字符串常量则可以含一个或多个字符。,3)可以把一个字符常量赋予一个字符变量,但不 能把一个字符串常量赋予一个字符变量。因为在语言中没有相应的字符串变量,如果想将一个字符串存放在变量中,必须使用字符数组,即用一个字符型数组来存放一个字符串,数组中每一个元素存放一个字符。这将在数组一章内介绍。 4)字符常量占一个字节的内存空间。字符串常量 在存放时系统一般会在这个字符串的后面加上字符0 (ASCII值为0) 即“字符串结束标志”,所以所占的内存字节数等于字符串中字节数加1。,例如: 字符串 “C program“ 在内存中所占的字节为: 字符常量b和字符串常量“b“虽然都只有一个字符,但在内存中的情况是不同的。 a在内存中占一个字节,可表示为: “a“在内存中占二个字节,可表示为:,2.2.4 符号常量,在语言中,可以用一个标识符来表示一个常量,称之为符号常量。符号常量在使用之前必须先定义,其一般形式为: #define 标识符 常量 其中#define是一条预处理命令(预处理命令都以“#“开头),称为宏定义命令(在后面预处理程序中将进一步介绍),其功能是把该标识符定义为其后的常量值。符号常量一经定义就只能代表被定义的那个常量或表达式,不能再作更改。习惯上符号常量的标识符用大写字母,变量标识符用小写字母,以示区别。使用符号常量的好处是:含义清楚;能做到“一改全改”。比如下面例子,如果半径R变成15,则只需在前面改一处即可。,【例2.2】符号常量的使用。 #define PI 3.1415926 #define R 12 main() float c,s; c=2* PI*R; s=PI*R*R; printf(“c=%f,s=%f”,c,s); ,2.3 变量,2.3.1 变量概述、标志符 变量就是运行过程中其值可以改变的量。变量要有变量名,在内存中占据一定的存储单元,存储单元里存放的是该变量的值。不同类型的变量存储单元的大小不同。要区分变量名和变量值是两个不同的概念,具体见图2-3。 变量名实际上是一个符号地址,代表内存中一定的存储单元,程序从变量中取值,实际上是通过变量名找到相应的内存地址,然后从其存储单元中读取数据。,变量必须先定义后使用,定义变量实际 上是为了在内存里为此变量分配相应的存储单元。要定义变量,必须给变量命名,和其他高级语言一样,变量的命名必须符合标志符的命名规则。标志符(identifier)是一个名字,即是用来标志变量名、常量名、函数名、数组名、数据类型名和程序名等的有效字符序列。,C语言标志符的命名规则如下: 1. 由字母(区分大小写)、数字和下划线组成; 2. 由字母(区分大小写)或下划线开头; 3. 用户标志符不能使用程序中具有特殊意义的关键字,避免与C语言库函数以及用户编制的函数名相同(如相同则会造成它们不可用)。,【例2.3】以下不能定义为用户标识符的是: A)scanf B)Void C)_3com_ D)int 答案:D 在使用标志符时,不仅要注意上面的规则,还要注意不同系统对标志符长度的要求也是不同的,比如我们常用的Turbo C就允许32个字符;其次,还要注意在选择变量名和其他标志符时,应尽量做到“见名知意”,即选有含义的英文单词(或其缩写)或其汉语拼音作标志符,如sum,name,year,total,zongshu等,除了数值计算程序外,一般不要用代数符号(如a,b,x,y1,i等)作变量名,以增加程序的可读性。 下面各节分别介绍整型、实型(浮点型)和字符型变量。,2.3.2 整型变量,前面我们学习了整型常量,如果要对这些整型常量进行存储的话,我们一般要定义整型变量来存放。下面我们就来学习整型变量。 1. 整型数据在内存中的存放形式 数据在内存中是以二进制补码形式存放的。如定义了一个整型变量a: int a; a=10; 在C语言里面,每个整型变量在内存中存放占2个字节。十进制整数10的二进制形式是1010,扩展为2个字节即为:0000000000001010,关于补码,这里在作一点说明: (1)、正数的补码和原码相同; (2)、负数的补码:等于该数的绝对值的二进制按位取反再加1。 例如: 求-10的补码: 10的原码: 0000000000001010 取反: 1111111111110101 再加1,得-10的补码: 1111111111110110 由此可知,整数的16位中,最左面的第一位是表示符号的,该位为0,表示数值为正;为1,表示数值为负数。,2. 整型变量的分类 整型变量的基本类型符为int,在int之前可以根据需要分别加上修饰符(modifier):short(短型)或long(长型),得到以下三种整型变量: (1)、基本整型:类型说明符为int,在内存中占2个字节。 (2)、短整型:类型说明符为short int或short。所占字节和取值范围与基本整型相同。 (3)、长整型:类型说明符为long int或long,在内存中占4个字节。,事实上,上面三种类型的整型都是有符号的,如在Turbo C中int型变量的取值范围为-3276832767。在实际应用中,变量的值常常是正的,如学号、年龄、库存量等等,针对这些情况,C语言可以加上修饰符unsigned,以指定是无符号数,相反,如果加上signed则表示是有符号数。既不指定unsigned也不指定signed,则隐含为有符号的(signed)。如上面归纳的几种类型均表示是有符号的。,归纳起来,可以用以下六种整型变量: n 有符号基本整型: signed int n 无符号基本整型: unsigned int n 有符号短整型: signed short int n 无符号短整型: unsigned short int n 有符号长整型: signed long int n 无符号长整型: unsigned longint,各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位(有符号数在存储单元中最高位表示符号,最高位为0表示正数,为1表示负数),不能表示负数,故一个无符号整型变量中可以存放的正数的范围比一般整型变量中正数的范围扩大一倍。 有符号整型变量:最大表示32767 0111111111111111 无符号整型变量:最大表示65535 1111111111111111,表2-3 整数类型表,一个整数,以10为例,在存储单元中的中的存储情况见下图: int型:0000000000001010 short int型:0000000000001010 long int型: 00000000000000000000000000001010 unsigned int型: 0000000000001010 unsigned short int型:0000000000001010 unsigned long int型: 00000000000000000000000000001010,1. 整型变量的定义 前面提到,C语言是一种强类型语言,里面所有用到的变量都必须先定义后使用。 变量定义的一般形式为: 类型说明符 变量名标识符1,变量名标识符2,; 例如: int a,b,c; (指定a,b,c为整型变量) long x,y; (指定x,y为长整型变量) unsigned p,q; (指定p,q为无符号整型变量),【例2.4】整型变量的定义与使用。 main() int a,b,c,d; unsigned u; a=12;b=-24;u=10; c=a+u;d=b+u; printf(“a+u=%d,b+u=%dn”,c,d); 运行结果: a+u=22,b+u=-14,1. 整型数据的溢出 在Turbo C中,所有整型都有一定的取值范围,比如一个int型变量的最大允许值为32768,如果再加1,会出现什么情况呢? 【例2.5】整型数据的溢出。 main() int a,b; a=32767; b=a+1; printf(“a=%d,b=%dn“,a,b); ,运行结果如下: a=32767,b=-32768 a:32767: 0111111111111111 b:-32768 1000000000000000 从上图可以看出,变量a的最高位为0,其他位全为1,加1后最高位变为1,其他位变为0,即从一个正数变成了一个负数,而这个负数是-32768的补码形式,所以输出变量b的值为-32768。在数学里面32767加1是32768,现在却变成了-32768,这种情况即是C语言里面所谓的“溢出”现象,运行时是不会报错的,就像时钟里面的计时,每天时钟转到23:59:59再过一秒就又从0开始计时。要解决这种问题,我们就要先估算数据的大小,然后再选择一种合适的数据类型,比如上例中,将b改为long型就可以得到预期结果32768了。,2.3.3 实型变量,前面我们学习了实型常量,这节我们来学习实型变量。首先来了解实型变量的分类。 1. 实型变量的分类 实型变量分为:单精度(float型)、双精度(double型)和长双精度(long double型)三类。有关规定见表2-4:,表2-4 实数类型,在Turbo C中单精度型占4个字节(32位)内存空间,只能提供7位有效数字。双精度型占8 个字节(64位)内存空间,可提供16位有效数字。 实型变量定义的格式和书写规则与整型相同。 例如: float x,y; (x,y为单精度实型量) double a,b,c; (a,b,c为双精度实型量),1. 实型数据的舍入误差 由于实型变量是由有限的存储单元组成的,因此能提供的有效数字总是有限的,在有效位以外的数字将被舍弃。由此会产生一些误差。如下例。 【例2.6】实型数据的舍入误差。 main() float a,b; a=987654.123e5; b=a+50; printf(“%fn“,a); printf(“%fn“,b);,运行结果如下: 98765414400.000000 98765414400.000000 程序运行时,出现a值和b值相等,原因是:987654.123e5+50本来等于98765412350,但是一个单精度型变量只能保证的有效位只有7位,超过的数字是无意义的,因此才会出现上面的a和b的值相等且不准确的现象。与此类似,1.0/3*3的结果并不等于1也是这个原因。,【例2.7】 main() float a; double b; a=33333.33333; b=33333.33333333333333; printf(“%fn%fn“,a,b); 运行结果如下: 33333.332031 33333.333333,从本例可以看出,由于a 是单精度浮点型,有效位数只有七位。而整数已占五位,故小数二位后之后均为无效数字。b 是双精度型,有效位为十六位。但Turbo C 规定小数后最多保留六位,其余部分四舍五入。,2.3.4 字符变量,字符变量用来存储字符常量,即单个字符。字符变量的类型说明符是char。字符变量类型定义的格式和书写规则都与整型变量相同。例如: char a,b;(定义a和b为字符类型变量,各可以放一个字符) 对字符变量赋初值可以采用以下方式: a=a;b=b;(将字符常量a赋值给变量a,字符常量b赋值给变量b),字符数据在内存中的存储形式及使用方法 每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。 如x的十进制ASCII码是120,y的十进制ASCII码是121。对字符变量a,b赋予x和y值: a=x; b=y; 实际上是在a,b两个单元内存放120和121的二进制代码: a:01111000 b:01111001 所以也可以把它们看成是整型量。语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。,整型量为二字节量,字符量为单字节量,当整型量按字符型量处理时,只有低八位字节参与处理。 【例2.8】向字符变量赋以整数。 main() char a,b; a=120; b=121; printf(“%c,%cn“,a,b); printf(“%d,%dn“,a,b); ,运行结果如下: X,y 120,121 本程序中定义a,b为字符型,但在赋值语句中赋以整型值。从结果看,a,b值的输出形式取决于printf函数格式串中的格式符,当格式符为“c“时,对应输出的变量值为字符,当格式符为“d“时,对应输出的变量值为整数。,【例2.9】 main() char a,b; a=a; b=b; a=a-32; b=b-32; printf(“%c,%cn%d,%dn“,a,b,a,b); ,运行结果如下: A,B 65,66 本例中,a,b被说明为字符变量并赋予字符值,语言允许字符变量参与数值运算,即用字符的ASCII 码参与运算。由于大小写字母的ASCII 码相差32,因此运算后把小写字母换成大写字母。然后分别以整型和字符型输出。,2.3.4 变量赋初值,我们在前面学习了几种常见的变量,明确了变量必须先定义然后才能使用,当然,使用的第一步一般就是给变量赋初值了。 总结一下,变量赋初值一般有以下几种方式: (1)、先定义,后赋初值。如: float a; char c1,c2; a=3.4; c1=a;c2=k; (2)、在定义变量时赋初值。如上例可以写成: float a=3.4; char c1=a,c2=k;,当然,在第一种方式中除了直接赋值以外,还可以定义好后从键盘进行赋值或者通过计算获得初值。其上两种方法也可以混合使用。 如:float a3.4; char c1,c2k; c1=a;(或从键盘输入:scanf(“%c“,),2.3.5 不同类型数据间的相互转换,变量的数据类型是可以转换的。转换的方法有两种,一种是自动转换,一种是强制转换。,一、 自动类型转换: 自动转换发生在不同数据类型的量混合运算时,由编译系统自动完成。 当不同类型数据混合运算时,依据如下规则: 1) 若参与运算量的类型不同,则先转换成同一类型,然后进行运算。计算结果的类型为表达式中数据长度最高数值的类型。 2) 转换按数据长度增加的方向进行,以保证精度不降低(详见图2-3)。如int型和long型运算时,先把int量转成long型后再进行运算。 3) 所有的浮点运算都是以双精度进行的,即使仅含float单精度量运算的表达式,也要先转换成double型,再作运算。 4) char型和short型参与运算时,必须先转换成int型。,下图表示了类型自动转换的规则。,【例2.10】 main() float PI=3.14159; int s,r=5; s=r*r*PI; printf(“s=%dn“,s); 运行结果如下: S=78,本例程序中,PI为实型;s,r为整型。在执行s=r*r*PI语句时,r和PI都转换成double型计算,结果也为double型。但由于s为整型,故赋值结果仍为整型,舍去了小数部分。,当做赋值运算时:若赋值号左右两边的类型不同,则赋值号右边的类型向左边的类型转换;当右边类型高于左边时,转换过程中自动对右边数据截断。所以,往往高类型数据赋给低类型变量时,会有数据丢失的现象,这样会降低数据的精度,丢失的部分按四舍五入向前舍入。,二、强制类型转换 强制类型转换是通过类型转换运算来实现的。 其一般形式为: (类型说明符) (表达式) 其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。 例如: (float) a 把a转换为实型 (int)(x+y) 把x+y的结果转换为整型,在使用强制转换时应注意以下问题: 1) 类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。 2) 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。,【例2.11】若有定义:int a=2,b=3;float x=3.5,y=2.5;则下面表达式以%f形式输出到屏幕的值为( ) (float)(a+b)/2+(int)x%(int)y A) 3.5 B) 35 C) 3.500000 D) 3.000000 答案:C 解析:注意(float)(a+b)/2+(int)x%(int)y中(float) 只是对(a+b)的结果进行强制类型转化,若希望对 (a+b)/2,则应该写成(float)((a+b)/2);后面的两个(int)分别是对 x和y进行强制类型转换;以%f形式输出,系统自动输出到小数点后6位。,2.3.6 数值的定点表示形式与浮点表示形式,数值在表示形式上总的来说可以分为定点表示形式和浮点表示形式。那么究竟什么是“定点”什么是“浮点”呢?在前面学习的数值里面我们知道整数是没有小数点的,实数才有小数点,而实型常量在表示形式上又可以分为十进制小数形式和指数形式,在这里,我们把凡不带指数部分的数称为“定点数”,如:3.1415、102、-88等,显然,正数都属于定点数,在计算机中以二进制形式存储。,如正数11的16位(占两个字节)存储形式为: 0000000000001011 如果在程序中出现了小数形式的实数(如0.31415),C语言则把它按指数形式存放,因为C语言里将实数一律以浮点形式存储。 为了理解“浮点”这个概念,我们先看值的几种表示形式: 日常的表示法 C语言中的表示形式 3.14159100 3.14159e0 31.415910-1 31.4159e-1 314.15910-2 314.159e-2 0.314159101 0.314159e1 0.0314159102 0.0314159e2,从上例可以看出,以指数形式表示的数据可以通过改变小数点的位置和其后面指数的值而变化表示形式,即,由于“指数”的存在以及它的大小不同而使“数字部分”的小数点位置不同,小数点的位置是“浮动的”,这种形式称为浮点数形式。在上面指数中,e前面的数字部分又称“尾数”,e及后面的指数部分又称“阶码”。在前面学习中,我们知道实型常量在表示形式上分为小数形式和指数形式,指数形式数据在输出时一律以“规范化指数形式”输出,这时在表示形式上来说的,在计算机内部,凡实数都以浮点形式(即指数形式)存储,指数部分采用规范化的指数形式。,很多编译系统中一个实数一般用4个字节(32位)存储,其中3个字节存放数字部分(第一位存放符号),一个字节存放指数部分(阶码),见下图。实际上,在计算机内是以二进制形式表示这些数的,平时我们的数据以十进制数表示只是为了容易理解。,2.4 运算符和表达式,语言中运算符和表达式数量之多,在高级语言中是少见的。C语言把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理。在语言的表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约,以便确定是自左向右进行运算还是自右向左进行运算。,2.4.1 C运算符简介,C语言运算符种类繁多,按参与运算的对象个数又可以这样分类:单目运算符、双目运算符和三目运算符。如+和!等是单目运算符,/和&等是双目运算符,C语言中有且仅有条件运算符 ? : 是三目运算符。 本章只介绍算术运算符、赋值运算符和逗号运算符,其他运算符在以后各章会陆续介绍。,2.4.2 算术运算符和算术表达式,1. 基本的算术运算符 加法“+”、减法“-”、乘法“*”、除法运算符“/”:这四个运算符是我们最为熟悉的运算符(注意乘法和除法运算符号与数学里面的不同),均为双目运算符,应有两个运算量参与运算。具有自左向右的结合性。如9+6、77/5、4*25等。求余运算符“”得到的结果是“”号左右两边操作数相除后的余数,如95值为4。,注意: (1)、“+”和“-”还可以做正负号使用,当做正负号时,为单目运算符。 (2)、“/”运算符有一个特点,就是当“/”左右两边数据均为整数时,得到的结果也是整数,所以1/2值为0,而如果希望得到值是0.5的话就要将表达式改成1.0/2或1/2.0。 (3)、“”运算符两边的运算数必须都是整型数据。如12.56为非法。且余数的符号由被除数的符号决定。如-5%4值为-1,5%-4值为1。,【例2.12】求a、b、c三个整数的平均值。 main() int a=0,b=1,c=b%3; printf(“Thefirst everage is :%fn“,(a+b+c)/3); printf(“Thesecondeverage is :%fn“,(a+b+c)/3.0); ,运行结果如下: The first average is:0.000000 The second average is:0.666667 本例中,要求三个整数a、b和c的平均值,b%3中b除以3的余数是1,所以c的值为 1。按数学的观点就是求23,其值应该是一个小数。 今两个输出都是以%f(即实数形式)输出,但是(a+b+c)/3的值为0,而(a+b+c)/3.0的值为0.666667,正好验证上面的几条规则。,2. 算术表达式和运算符的优先级和结合性 表达式是由常量、变量、函数和运算符组合起来的式子。表达式求值按运算符的优先级和结合性规定的顺序进行。单个的常量、变量、函数可以看作是表达式的特例。 算术表达式是由算术运算符和括号连接起来的式子。,(1)、算术表达式:用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子。 以下是算术表达式的例子: (x+r)*8-(a+b)7+w +i,(2)、运算符的优先级:语言中,各种运算符都遵循一定的优先级规则。运算符的运算优先级共分为15级。在表达式中,优先级较高的先于优先级较低的进行运算例如先乘除后加减。当一个运算量两侧的运算符优先级相同时,则根据运算符的结合性来处理,一般来说,所有的运算符中基本有如下优先关系:初等运算符单目运算符算术运算符(先乘除后加减)关系运算符逻辑运算符条件运算符赋值运算符逗号运算符。由此可见,初等运算符的优先级是最高的,单目运算符的优先级高于双目运算符的优先级。,(3)、运算符的结合性:语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应先与“-”号结合,执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。 最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。语言运算符中有不少为右结合性,如:所有的单目运算符、赋值运算符和条件运算符都是右结合性。通过后面的学习我们来慢慢领会。,3. 自增、自减运算符 其作用是使变量的值自增1或自减1。 +i,-i (先使i自增(减)1,然后再参与其他运算) i+,i- (i先参与其他运算后,i的值再自增(减)1) 总的来说,+i和i+都包含一个i=i+1的操作,-i和 i-都包含一个i=i-1的操作,但要注意一个是作为前缀使用(需先自增/减,后使用),一个作为后缀使用(需先使用,后自增/减),这个问题比较难理解,我们先来看看下面例子。,【例2.13】 main() int a=1,b; b=a+;/*相当于b=a;a=a+1;*/ printf(“(1).a=%d,b=%dn“,a,b); b=+a;/*相当于a=a+1;b=a;*/ printf(“(2).a=%d,b=%dn“,a,b); b=a-;/*相当于b=a;a=a-1;*/ printf(“(3).a=%d,b=%dn“,a,b); b=-a;/* 相当于a=a-1;b=a;*/ printf(“(4).a=%d,b=%dn“,a,b); ,运行结果为: (1).a=2,b=1 (2).a=3,b=3 (3).a=2,b=3 (4).a=1,b=1 通过这个例子,我们应该对自增自减运算符有所理解了。,但是也要注意下面这种形式: 【例2.14】 main() int i=5,j=5,p,q; p=(i+)+(i+)+(i+); q=(+j)+(+j)+(+j); printf(“%d,%d,%d,%d“,p,q,i,j); 运行结果如下: 15,24,8,8,这个程序中,对P=(i+)+(i+)+(i+)应理解为三个i相加,故P值为15。然后i再自增1三次相当于加3故i的最后值为8。而对于q 的值则不然,q=(+j)+(+j)+(+j)应理解为q先自增1,再参与运算,由于q自增1三次后值为8,三个8相加的和为24,j的最后值仍为8。 注意: (1)、自增自减运算符只能用于变量,不能用于常量和表达式 (2)、其结合性是自右至左。 (3)、自增自减运算符可以比i=i+1的形式节省运算时间,但是这种运算尤其是例2.15中的形式容易使编程者造成混乱,为了程序的可读性,不建议任意使用此运算符。,2.4.3 赋值运算符和赋值表达式,1. 赋值运算符 简单赋值运算符和表达式:简单赋值运算符记为“=”。由“= ”连接的式子称为赋值表达式。其一般形式为: 变量=表达式 例如: x=a+b w=sin(a)+sin(b) 赋值表达式的功能是计算表达式的值再赋予左边的变量。赋值运算符具有右结合性。因此 a=b=c=5(注意思考int a=b=c=5;为非法是为什么?) 可理解为: a=(b=(c=5),在使用赋值号时还应注意: (1)、在程序中可以多次给一个变量赋值,每赋一次值,它所对应的存储单元中的数据就被更新一次,内存中当前的数据就是最后一次所赋值的那个数据。 (2)、不能给符号常量赋值,如先定义define N 5则N就代表5,不能再赋值如N=N+3 或N+;不能给表达式赋值,如:假设a、b均已经赋值,则c=a+b=21错误 (3)、还可以出现这样的赋值语句:x=(a=5)+(b=8),它的意义是把5赋予a,8赋予b,再把a,b相加,和赋予x,故x应等于13。,2. 类型转换 如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,即把赋值号右边的类型换成左边的类型。这在前面2.3.5节中已述,这里具体讲一下转换规则。 (1)、实型(包括单、双精度)赋予整型,舍去小数部分。前面的例子已经说明了这种情况。整型赋予实型(包括单、双精度),数值不变,但以浮点形式存放,即增加小数部分(小数部分的值为0)。,(2)、字符型赋予整型,由于字符型为一个字节,而整型为二个字节,故将字符的ASCII码值放到整型量的低八位中,高八位则要分情况处理,如果是无符号字符,或最高位为0的有符号字符,则高8位补0,最高位为1的有符号字符,则高8位补1。整型赋予字符型,只把低八位原封不动地赋予字符量,高位舍弃(简单截断)。,(3)、int型赋给long型时,将int原封不动赋给long的低16位,如int为整数(即符号位为0),则long高16位赋0,为负数则高16位赋1。long赋给int只取其低16位,高位舍弃。,(4)、将unsigned int型数据赋给long型变量时,只需将高位补0即可;相反,long型数据赋给unsigned int型变量时也是简单舍弃高16位取其低16位。将一个unsigned类型数据赋给一个占字节数相同的整型变量时,将unsigned型变量的内容原样送到非unsigned型变量中;将非unsigned型数值赋给一个长度相同的unsigned型变量,也是原样赋值(连原有的符号位也作为数值一起传送)。,【例2.15】 main() int a,b=322; float x,y=8.88; char c1=k,c2; a=y; x=b; a=c1; c2=b; printf(“%d,%f,%d,%c“,a,x,a,c2); ,运行结果如下: 107,322.000000,107,B 本例表明了上述赋值运算中类型转换的规则。a为整型,赋予实型量y值8.88后只取整数8。x为实型,赋予整型量b值322, 后增加了小数部分。字符型量c1赋予a变为整型,整型量b赋予c2 后取其低八位成为字符型(b的低八位为01000010,即十进制66,按ASCII码对应于字符B)。,【例2.16】 main() unsigned int a; int b=-1; a=b; printf(“a=%un“,a); ,“%u”是输出无符号数时所用的格式符。运行结果如下: a=65535 a :1111111111111111 b :1111111111111111 a为无符号整型,b为有符号整型,赋值情况见上图,如果b为正值,且在032767之间,则赋值后数值不变。,3. 复合的赋值运算符 在赋值符“=”之前加上其它双目运算符可构成复合赋值符。如+=,-=,*=,=,%=,=,&=,=,|=。 例如: a+=b 等价于a=a+b a*=b+3 等价于a=a*(b+3) a%=b 等价于a=a%b 复合赋值符这种写法,对初学者可能不习惯,但十分有利于编译处理,能提高编译效率并产生质量较高的目标代码。,2.4.4 逗号运算符和逗号表达式,在语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个及以上表达式连接起来组成一个表达式, 称为逗号表达式。 其一般形式为: 表达式1,表达式2 求解过程:从左往右算,先求表达式1,然后求表达式2,整个逗号表达式的值是表达式2或称最后一个表达式的值。,【例2.17】 main() int a=2,b=4,c=6,x,y,z; z=(y=(x=a+b),(b+c); printf(“y=%d,x=%d,z=%d“,y,x,z); 运行结果如下: y=6,x=6,z=10,对于逗号表达式还要说明两点: (1)、逗号表达式一般形式中的表达式1和表达式2 也可以又是逗号表达式。 例如: 表达式1,(表达式2,表达式3) 形成了嵌套情形。因此可以把逗号表达式扩展为以下形式: 表达式1,表达式2,表达式n 整个逗号表达式的值等于表达式n的值。,(2)、程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值。 并不是在所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中逗号只是用作各变量之间的间隔符。 如: for(i=1,sum=0,i100,i+) for语句的第一个表达式就是逗号表达式,用来对变量进行初始化。,2.5 上机实训,试验目的 l 了解C语言各数据类型的意义,掌握各种类

温馨提示

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

评论

0/150

提交评论