480 likes | 623 Views
第三章 数据类型、运算符与表达式. 3.1 C 的数据类型 3.2 常量与变量 3.3 三种基类型数据 3.4 运算符和表达式 3.5 练习. 3.1 C 的数据类型. 图 3.1 C 的数据类型总览. 3.1.1 三种基本数据类型(存储形式). 1. 整型 整型数据在内存中以二进制补码形式存放,一般占 2 个 字节。. 正数的补码和其原码相同,负数的补码为其绝对值的原码按位取反再加 1 。. 10 的补码: 0000 0000 0000 1010 (等于原码)
E N D
第三章 数据类型、运算符与表达式 3.1 C的数据类型 3.2 常量与变量 3.3 三种基类型数据 3.4 运算符和表达式 3.5 练习
3.1 C的数据类型 图3.1 C的数据类型总览
3.1.1 三种基本数据类型(存储形式) 1. 整型 整型数据在内存中以二进制补码形式存放,一般占2个 字节。 正数的补码和其原码相同,负数的补码为其绝对值的原码按位取反再加1。 10的补码:0000 0000 0000 1010(等于原码) -10的补码:1111 1111 1111 0110 符号位
2. 字符型 字符型数据在内存中以ASCII码存放(附录I),存储 形式与整数类似,只占一个字节。 ‘A’:0100 0001 3. 实型 实型数据在内存中按指数形式存储,分成小数部分和 指数部分,一般占4个字节。
3.2 常量与变量 3.2.1 常量 常量是其值在程序运行过程中不能被改变的量。 常量又可以分为直接常量和符号常量。直接常量可以从字面上直接看出数据的类型和值;而符号常量是用一个标识符来代表一个常量,不能从字面上直接看出数据的类型和值。 用于为语法单位命名的有效字符序列称为标识符。C语言规定标识符只能由字母、数字和下划线三种字符组成,并且不能以数字开头。
合法 非法 _total 1_total test1_2 test1-2 PI hi!there a1 a1 A1 f(x) Int int 注意:大小写敏感,不能用关键字作为标识符(附录Ⅱ)。
符号常量的使用 宏定义命令#define用来定义一个标识符和一个字符串,在程序中每次遇到该标识符时就用所定义的字符串替换它。这个标识符叫做宏名,替换过程叫做宏替换或宏展开。宏定义命令#define的一般形式是: #define 宏名 字符串 例如想用PI表示数值3.1415926,就可以用宏定义#define来说明: #define PI 3.1415926 这样在预编译时,每当在源程序中遇到PI就自动用3.1415926代替,这就是宏展开。
例 求半径为3的圆的周长和面积。 #define PI 3.1415926 main( ) {float perimeter,area; perimeter=2*PI*3; area=PI*3*3; printf(“周长=%f,面积=%f\n”,perimeter,area); } 经过宏替换,宏展开为: perimeter=2*3.1415926*3; area=3.1415926*3*3;
注意: (1)宏替换仅是简单地用所说明的字符串来替换对应的 宏名,无实际的运算发生,也不作语法检查。 例如: #define PI 3.1415926; … perimeter=2*PI*3; area=PI*3*3; 经过宏替换后, 语句展开为: perimeter=2*3.1415926;*3*3; area=3.1415926; *3*3; 然后经编译将出现语法错误。
(2)符号常量的值在其作用域(从定义开始,到源程序(2)符号常量的值在其作用域(从定义开始,到源程序 结束为止)内不能改变。 例如: #define PI 3.1415926 … PI=3.14; perimeter=2*PI*3; area=PI*3*3; 经编译将出现语法错误。 (3)在C语言程序中习惯上用大写字母作为宏名。
3.2.2 变量 变量是其值在程序执行过程中可以改变的量。 若有定义 int sum; 则执行语句 sum=0; 后, 它的值为0; 可再执行语句 sum=1; 将它的值变为1。 每个变量都有一个名字,它代表某个存储空间及其所存储的数据。在程序中取变量的值,实际上是通过变量名找到相应的存储单元,从中读取数据。要想把内存中的某段存储单元和一个变量名联系起来, 必须首先对变量进行定义或声明。
1. 变量的定义 变量定义的一般形式: 类型说明符 变量名表; 这里,类型说明符(type)必须是C语言的有效数据类型。 变量名表可以是一个或多个标识符名,中间用逗号分隔, 最后以分号结束。 如:int a,b; float f1,f2; char ch; 这样就在内存中开辟了五个相应的存储单元,这五个单 元在空间上不一定是连续的。
等价于 2. 变量的初始化 变量定义后,相应的存储单元内并没有确定的数据。 因此,使用变量时要先对变量进行初始化。 C语言允许在定义的同时为变量初始化。 如:int a,b; a=2; b=3; int a=2,b=3; 2 3 a b
3. 说明 (1)变量必须先定义后使用。 (2)同一函数内所定义的变量,变量名不能相同。 错误:int a; float a; (3)变量使用时要先初始化,给出相应的初值,可在定 义的同时初始化。 正确:① int a,b; a=b=2; ② int a=2,b=2; 错误:int a=b=2;
3.3 三种基类型数据 3.3.1 整型数据 1. 整型常量的表示方法 (1)十进制整数:用十进制数码表示数,不加前缀。 如:123,-123。 (2)八进制整数:用八进制数码表示数,加前缀0(数字 零)。如:0123,-0123。 (3)十六进制整数:用十六进制数码表示数,加前缀0x 或0X(数字零和字母x(X))。如:0x123,-0X123。 注意:123≠0123≠0x123
2. 整型变量的分类 (1)基本整型(int):占2个字节 (2)短整型(short int或short):占2个字节 (3)长整型(long int或long):占4个字节 这三类前都可以加上修饰符signed或unsigned。 (1)signed:有符号型,最高位为符号位,可缺省。 (2)unsigned:无符号型,最高位为数据位,不可缺省。 如有: int a; unsigned int b; 则a为有符号基本整型,b为无符号基本整型。
无符号型变量由于无符号位,只能存放非负整数。而有符号型变量最高位为符号位,0表示正数,1表示负数,因此可存放负数。无符号型变量由于无符号位,只能存放非负整数。而有符号型变量最高位为符号位,0表示正数,1表示负数,因此可存放负数。 int : -32768 0 32767 unsigned int : 0 65535 图3.2 int类型和unsigned int类型的取值范围
a: 0111 1111 1111 1111 + 0000 0000 0000 0001 b: 1000 0000 0000 0000 符号位 3. 整型数据的溢出 各种整数类型都有各自的取值范围,一旦越出了这个 范围,就不能正确地表示数据,这种情况称为“溢出”。 main( ) {int a,b; a=32767; b=a+1; printf(“%d,%d\n”,a,b); } 编译,运行结果为:32767,-32768
a: 1000 0000 0000 0000 - 0000 0000 0000 0001 b: 0111 1111 1111 1111 符号位 main( ) {int a,b; a=-32768; b=a-1; printf(“%d,%d\n”,a,b); } 编译,运行结果为:-32768,32767 注意:常量无unsigned型;整型数据加后缀l或L,表示长 整型常量,即123≠123L。
3.3.2 实型数据 1. 实型常量的表示方法 (1)十进制小数形式:有数字和小数点组成(必须有小 数点)。如:123.0、123.、.123。 (2)指数形式:<数字>e(或E)<整数> 正确:12.3e1、1.23E2、1230e-1。 错误:e3、2.1e3.5、.e3、e。 若要表示1.0×103? 1.0e3或1e3
2. 实型变量的分类 (1)单精度型:float,占4个字节,7位有效数字。 (2)双精度型:double,占8个字节,16位有效数字。 (3)长双精度型:long double,占16个字节。 3. 实型数据的舍入误差(由有效位造成) main( ) {float a,b; a=123456.789e5; b=a+20; printf(“%f\n”,b); }
3.3.3 字符型数据 1. 字符常量 字符常量是用单引号括起来的一个字符。 如:‘a’、‘1’、‘?’等。 注意: (1)大小写敏感:‘a’和‘A’是不同的字符常量。 (2)‘1’和1不同:前者是字符常量,ASCII值为49;后者 为整型常量,值为1。 (3)单引号仅为字符常量的定界符,而非字符常量的一 部分。 (4)单引号内的那个字符不能为单引号、双引号或反斜 杠。
转义字符:以\(反斜杠)开头的字符序列。 ‘\n’: 回车换行符 ‘\r’: 回车符 ‘\t’: 跳过一个8列 ‘\b’: 退格符 ‘\f’: 换页符 ‘\\’: 反斜杠 ‘\’’: 单引号 ‘\”’: 双引号 ‘\ddd’: 八进制数所代表的字符 ‘\xhh’:十六进制数所代表的字符
例 main( ) {printf(“This is a program.\n”); printf(“\this is\ba\012program.\n”); printf(“\”first\\second\””); } 运行结果为: This is a program. his ia program. “first\second”
字符串常量是用一对双引号括起来的字符序列。字符串常量是用一对双引号括起来的字符序列。 2. 字符串常量 系统自动地在每个字符串常量的末尾加一个“字符串结束 标志”(‘\0’)。它是一个空操作符,不做任何操作。 注意: (1)大小写敏感:“a”和“A”是不同的字符常量。 (2)‘1’和“1”不同:前者是字符常量,只包含一个字符; 后者为字符串常量,包含两个字符‘1’和‘\0’。 (3)双引号仅为字符串常量的定界符,而非字符串常量 的一部分。 (4)字符串中要插入双引号,应借助转义字符‘\”’。
3. 字符变量 由于字符型数据和整型数据的存储形式类似,所以两 者在一定范围内可互相通用。 (1)字符型数据和整型数据之间可以进行混合运算。 main( ) {char c; c=‘A’+32; printf(“%c\n”,c); } 运行结果为:a 可见,大小写字母的ASCII码值相差32。
0~255 (2)字符型数据和整型数据可互相赋值;字符型数据可 以用整数形式输出;反之,一定范围内的整数也可以用 字符形式输出。 main( ) {int I; char c; I=‘a’;c=97; printf(“%c,%d\n”,c,c); printf(“%c,%d\n”,I,I); } 运行结果为:a,97 a,97
3.4 运算符和表达式 3.4.1 表达式的基础 1.表达式是由运算符和操作数组成的。依据运算的特征, 可对表达式进行分类。 2.表达式在书写时应该注意遵循C语言表达式书写的原则: (1) C语言的表达式只能采用线性的形式书写。 例如: ① 应写成1.0/3+i+j*j*j。 ② 应写成(a+b)/(c+d)*e+f。
(2) C语言的表达式只能使用C语言中合法的运算符和操作数, 对有些操作必须调用库函数完成, 而且运算符不能省略。例如: ① πr2应写成3.14159*r*r。 ② 应写成0.5*a*b*sin(a)。 ③ |x-y|应写成fabs(x-y)。 ④ y+2X应写成y+pow(2, x)。
3.表达式的计算要考虑运算符的优先级和结合性。3.表达式的计算要考虑运算符的优先级和结合性。 运算符的优先级规定了运算符执行的先后顺序。C语言 将运算符的优先级划分为15级。(附录Ⅲ) 运算符的结合性是指,优先级相同的运算是从左到右进行(左结合性)还是从右至左进行(右结合性)。左结合性是人们习惯的计算顺序。 C语言中, 只有单目运算(!、 ~、 ++、 --、 -、*、 &)、条件运算(?: )、赋值运算(=、 +=、 -=、 *=、 /=、 %=)的结合性是右结合, 其余运算均为左结合。
double float 高 long unsigned 低 int char,short 4.表达式的计算还要考虑类型转换。 一般,各类运算是在相应的同一类型的数据之间进行 的。不同类型数据之间进行运算或数据类型不符合运算 要求时,要进行类型转换。类型转换有自动转换(又称 隐含转换)与强制转换两种方式。 (1)自动转换
横向箭头方向表示必定要进行的转换,纵向箭头方向横向箭头方向表示必定要进行的转换,纵向箭头方向 表示类型自动转换的方向(向高看齐)。 表达式中若有一数据为实型,则计算结果必为double类型。
(2)强制转换 强制类型转换通过类型转换运算进行。 格式:(类型名)(表达式) 将表达式的类型强制转换成类型名指定的类型。 如:float x=3.2, y=2.3; (int)(x+y) 将表达式x+y的值强制转换成整型。 (int) x+y 先将x的值转换成整型,再与y相加。 强制类型转换是暂时性的、一次性的,并不会永久地改变所转换表达式的类型。 如:int a=2; (double)a 为双精度,a依然为整型量。
3.4.2 算术运算符和算术表达式 1. 基本的算术运算符(+、-、*、/、%) 说明: (1)双目, *、/、% 优先级高于+、- ,左结合性。 (2)两个整型数据相除时,其运算结果也是整数,余数 被截掉。如1/2的结果是0;10/3的结果是3。 例 main( ) {int i=10, j=4; float f=i/j; printf(″f=%f\n″, f); } 运行结果为:f=2.000000
(3)求余运算符(%)仅用于整型数据,不能用于实型。(3)求余运算符(%)仅用于整型数据,不能用于实型。 它的作用是取整数除法的余数,结果与被除数同号。 如1%2的结果是1;-10%3的结果也是-1。 例 main( ) {int a; float f= -3.5; a=(int)f %10; printf(“a=%d\n”,a); } 运行结果为: a= -3
2. 自增、自减运算符(++、- -) 说明: (1)单目,操作数只能是变量,优先级处于第2级, 右结 合性。如 -i++等价于-(i++)。 (2)有前置、 后置两种方式: ① ++i 或 - -i :在使用i 之前,先使i 的值增/减1,俗称先加/减后使用。 ② i++ 或 i- - :先使用i 的值,然后使i 的值增/减1,俗称先使用后加/减。
main( ) {int x, y; x=10; y=++x; printf(“%d, %d\n”, x, y); } 运行结果为:11,11 若将第四行改为:y=x++; 则运行结果为:11,10
将程序改为: main( ) {int x, y; x=y=10; printf(“%d,%d\n”,++x,y++); } 运行结果为:11,10 若将第四行改为:printf( “%d,%d\n”,++x,x++); 则运行结果为:12,10 因为函数参数的求值顺序是自右而左。
3.4.3 赋值运算符和赋值表达式 1. 一般的赋值运算符和复合的赋值运算符 复合的赋值运算符是由赋值运算符和其它双目运算符 组合而成的。如:+ =、- =、* =、/ = 和 % = 。 格式:<变量> <赋值运算符> <表达式或量> 如:int x=0, a, b; a=2; b=a; x+=2; /*等价于x=x+2;*/ x*=a+b; /*等价于x=x*(a+b);*/ 则变量a、b的值都为2,变量x的值为8。
说明: (1)赋值运算符的左侧只能为变量。 非法:1 = a; - a=1; a+b=1; (2)双目,优先级别为14(仅比逗号运算符高),右结 合性。 例 int a=1, b, c; c=b=a ; a += a - =a*a ; /*等价于 a=a - (a*a) ; a=a+a ;*/ 则变量b、c的值都为1,变量a的值为0。
(3)当赋值运算符两侧数据的类型不一致,则在赋值时(3)当赋值运算符两侧数据的类型不一致,则在赋值时 要进行类型转换。 ① 实型→整型:取整,舍弃小数部分。 ② 整型→实型:数值不变,以实数形式表示。 ③ 单、双精度实型之间:数值不变,进行有效数字处理。 ④ 各种整型之间:按存储形式进行。 例 float x; int i; x=i=3.14159; 则变量i的值为3, 而变量x的值为3.0而不是3, 也不是 3.14159。
3.4.4 逗号运算符和逗号表达式 逗号运算符也称顺序求值运算符,其运算优先级为15, 也是最低的,结合方向是自左至右。逗号运算符把两个 对象“连接起来”,使之成为一个逗号表达式。 其一般形式是: <表达式1>,<表达式2>,…,<表达式n> 逗号表达式的求解过程: 先求解表达式1,再求解表达式2,…,最后求解表达 式n。整个逗号表达式的值是表达式n的值。
例如: x=(y=3, y+1) 该表达式括号内是逗号表达式,由于结合方向是自左 至右, 先将3赋给y, 然后计算表达式y+1,其值为4。整 个表达式的值为最后一个表达式的值,所以表达式的值 为4,最后将4赋给x。 若表达式改为: x=y=3, y+1 则表达式的值为4,x的值为3。
3.4.5 其它运算符 1. 取地址运算符& 取地址运算是单目运算, 操作数只能是变量, 得到变量 的地址。 2. 求字节数运算符sizeof 求字节数运算是单目运算, 操作数可以是类型名, 也可 以是变量、表达式,用以求得相应类型或数据所占的字 节数。 如:sizeof(int) 值为2 sizeof(‘A’) 值为1 sizeof(123+2L) 值为4 sizeof(“abc\”d\n”) 值为7
3.5 练习 一. 选择题 1. ( )是C语言提供的合法的数据类型关键字。 A.Float B.signed C.integer D.Char 2. ( )是非法的C语言转义字符。(多项选择) A.’\t’ B.’\018’ C.’\n’ D.’\0xaa’ 3. ( )是C语言的正确赋值语句。 A.a=1,b=2 B.a++; C.a=b=5 D.y=int(x); 4. 要求参加运算的数必须是整数的运算符是( )。 A./ B.& C.% D.= B B D B C
C 5. 执行以下语句后的输出为( )。 char ch=‘a’; ch - - ; printf(“%d,%c\n”, ch +’2’ - ’0’, ch +’3’ - ’0’ ); A.b,c B.a - -运算非法,故有语法错 C.98,c D.格式描述和输出项不匹配,输出无定值 6. 以下程序的输出结果是( )。 main( ) {int x=10,y=10; printf(“%d %d\n”, x- -, - -y);} A.10 10 B.9 9 C.9 10 D. 10 9 D
A 7. 以下程序的输出结果是( )。 main( ) {int m=7,n=4; float a=38.4,b=6.4,x; x=m/2+n*a/b+1/2; printf(“%f\n”,x);} A.27.000000 B.27.500000 C.38.000000 D.28.500000 8. 以下程序的输出结果是( )。 main( ) {int a=4,b=7; printf(“%d\n”, (a=a+1, a+b, b+1) ); A.5 B.8 C.12 D.无定值 B
1 2 v=0.5*a*t*t 二. 书写表达式 1. v= at2 2. 三. 计算表达式 1. ch=‘a’ + ’8’ – ‘3’ 2. a=2,b=5,a++,b++,a+b 3. a=25/3%3 4. 若有定义 int m=5,y=2; 则 y + = y - = m* = y x1=(-b+sqrt(b*b-4*a*c))/(2*a) ‘f’ 9 2 -16