第2章 数据类型与数据运算
2.1 要点难点阐述
1.数据类型
(1)基本类型
·枚举型。(用户自定义的)
(2)构造类型
·文件:当输入/输出的对象是磁盘时,使用文件类型(FILE)。(系统提供的)
(3)指针类型
指针类型是某种类型数据的地址类型。(用户自定义的)
(4)空类型
不需要数据类型时,使用空类型(void)。(系统提供的)
2.常量
常量是指在程序运行过程中其值不能改变的量。基本类型常量说明如表2-1所示。
表2-1 基本类型常量说明
3.变量
变量是内存的一个存储单元,存储单元内的当前值就是变量的值。其值在程序运行过程中可以改变,所以称为变量。变量必须先定义其数据类型,才能使用。基本类型变量的取值范围如表2-2所示。
表2-2 基本类型变量的取值范围
变量定义的一般格式为:
数据类型名 变量表;
其中,变量表中可以含多个变量,各变量之间用逗号分隔,分号标志着定义结束。例如:
int a,b,c;
变量可以在定义的同时初始化(即赋初值)。例如:
int a=1,b=2,c=3;
也可以对部分变量初始化。例如:
int a,b,c=5;
注意:在程序设计时,要根据使用数据的范围定义适合的数据类型的变量。若定义过大会浪费计算机资源,定义过小可能产生“溢出”或导致数据不精确。
4.数据运算
C语言规定了运算符的优先级别和结合性。在表达式求值时,先按运算符的优先级别高低次序进行运算,同级则按规定的“结合方向”处理。
(1)赋值运算
赋值运算符“=”的左侧必须是变量名,右侧是任意类型的表达式。
赋值表达式的求解过程:将赋值运算符右侧表达式的值送到左侧变量所代表的存储单元中。结合方向是右结合,优先级别较低,只高于逗号运算符。
做赋值运算时,系统对不同类型的数据自动进行类型转换。
①把实型数据赋给整型变量时,小数部分截去。
②长的数据给短的变量赋值,低位对齐赋值,高位丢失,有可能造成溢出。
③短的数据赋给长的变量,低位对齐赋值。对无符号数高位补0;对有符号数要进行“符号扩展”:即符号位为“0”,高位全补“0”;符号位为“1”,高位全补“1”。
(2)算术运算
①除法运算中,当两个操作数都是整型时,结果为整型,如1/4结果为0。
②求余运算中,两个操作数必须都是整型。
③自增/自减运算符的操作数只能是变量。在Turbo C中,若表达式中有自增/自减运算符,则应先扫描每一个变量的当前值,然后再计算表达式的值。例如:
int a=2,b=3,c;c=(++a)*(b--);
先扫描表达式(++a)*(b--),变量a先自增1,即当前值为3,b的当前值为3,所以c的值为3*3=9,然后b自减为2。所以,语句执行结束时a=3,b=2,c=9。
④数学表达式转换成C语言表达式要注意两点:一是乘法的乘号不能省略;二是恰当地使用圆括号以保证原来的逻辑关系不变。
(3)关系运算和逻辑运算
①关系运算和逻辑运算的结果都是一个逻辑值,即“真”或“假”。C语言没有逻辑数据,用“1”代表“真”,用“0”代表“假”。当进行运算时,非0即“真”,0即“假”。
②要注意关系表达式、逻辑表达式的书写,如数学中的不等式0<x<10,在C语言中应写成:x>0&&x<10。
③在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。
如a=0;b=1;c=a++&&b++;,其结果为a=1,b=1,c=0。最后一个赋值语句中赋值号右侧的逻辑表达式的求解过程为:逻辑与运算符左侧的表达式a++的当前值为0,则整个逻辑表达式值即为0,因此无须继续计算右侧的表达式,a自身增1,0赋给c,运算结束。
再如a=0;b=1;c=++a||++b;,其结果为a=1,b=1,c=1。最后一个赋值语句中赋值号右侧的逻辑表达式的求解过程为:逻辑或运算符左侧的表达式++a的值为1,则整个逻辑表达式值即为1,因此无须继续计算右侧的表达式,1赋给c,运算结束。
注意:当需要判断两个量是否相等时,运算符是由两个等号“==”组成的“等于”。注意一个等号“=”表示赋值。
(4)位运算
所谓位运算是指二进制位的运算,即运算的单位是二进制的一个位(bit)。
在程序中,若进行位运算的数据不是用二进制表示的,要先转换成二进制补码形式再运算,运算后的结果再转换成要求的进制。位运算有如下几种:
①按位与运算“&”:两个对应位均为1时该位结果为1,否则为0。运算的特点:与0相与对应位清零;与1相与对应位保留原值。
②按位或运算“|”:两个对应位均为0时该位结果为0,否则为1。运算的特点:与1相或对应位置1;与0相或对应位保留原值。
③按位异或运算“^”:两个对应位不同为1,相同为0。运算的特点:与1相异或对应位翻转;与0相异或对应位保留原值。
④按位取反运算“~”:就是0变1,1变0。
⑤左移运算“<<”:用来将一个数的各二进制位全部左移若干位,高位溢出舍弃,低位补0。操作数每左移一位,相当于乘以2。
⑥右移运算“>>”:用来将一个数的各二进制位全部右移若干位,低位舍弃。若无论操作数是正还是负都高位补0,称为“逻辑右移”;若操作数为正高位补0,为负高位补1,称为“算术右移”。操作数每右移一位,相当于除以2。
2.2 例题分析
【例2.1】 有变量定义语句int a=3;b=4;,则_______。
A.定义了a、b两个变量 B.定义了a、b两个变量,并均已初始化
C.程序编译时出错 D.程序运行时出错
解题知识点:变量定义语句规则。
解:答案为C。本题的解题要点是:变量定义语句以分号表示结束。b前面的分号标志着int型变量定义结束,则变量b未被定义。所以编译时出错:“Undefined symbol'b'in function…”。
【例2.2】 表达式3.5+5%2*(int)(1.5+1.3)/4的值为_______。
A.4.5 B.4.0 C.3.5 D.4.2
解题知识点:强制类型转换;算术运算。
解:答案为C。本题的解题要点是:做除法运算,当两个操作数都是整型时,结果为整型。因为5%2为1,(int)(1.5+1.3)为2,2/4为0,所以结果为3.5。
【例2.3】 有变量说明语句float a,b;int k=0;,合法的C语言赋值语句是_______。
A.a=b=8.5 B.a=8.5,b=8.5 C.k=int(a+b); D.k++;
解题知识点:强制类型转换;赋值语句的书写规则。
解:答案为D。赋值语句的一般格式为:变量名=表达式;,语句以分号作为结束标志。选项A是赋值表达式,不是语句;选项B是逗号表达式;选项C使用了强制类型转换,应将类型符用圆括号括起来,即k=(int)(a+b);;选项D相当于k=k+1;,所以是合法的赋值语句。
【例2.4】 有变量说明语句int a=9;,则执行完语句a+=a-=a*a;后,a的值是_______。
A.9 B.144 C.0 D.-144
解题知识点:复合赋值语句的运算规则。
解:答案为D。赋值语句的结合性为“自右至左”,复合赋值语句可以分解进行。将语句a+=a-=a*a;分解成如下两条语句:a-=a*a;a+=a;,由第一条语句可以算出a的值为-72,由第二条语句算出a的值为-144。
【例2.5】 有下面程序段:
int i,j;
j=(i=32767,i+1);
printf("i=%d,j=%d\n",i,j);
则运行结果是_______。
A.i=32767,j=32768 B.i=32768,j=32768
C.i=32767,j=-32768 D.i=32767,j=32767
解题知识点:逗号表达式;整型变量的取值范围。
解:答案为C。题中赋值语句j=(i=32767,i+1);,赋值号右侧的括号内是逗号表达式,执行过程为:先用32767为i赋值,再计算i+1的值,并用i+1的值作为逗号表达式的值为j赋值。在内存中的表示形式为:
可见,i+1的值为-32768。原因是整型变量在内存中占2个字节,最大可表示32767,再加1则产生溢出。
【例2.6】 下面程序段的运行结果是_______。
int x=5,y=5,z=5;
printf("x=%d,y=%d\n",x++,++y);
z++;++z;
printf("x=%d,y=%d,z=%d\n",x,y,z);
A.x=6,y=6 B.x=5,y=5
x=6,y=6,z=6 x=6,y=6,z=7
C.x=6,y=5 D.x=5,y=6
x=6,y=6,z=6 x=6,y=6,z=7
解题知识点:自增/自减运算符。
解:答案为D。第一个输出语句中的两个输出项都是表达式。x是后加操作,是先用变量的当前值作为表达式的值,然后变量的值加1;y是前加操作,是先为变量的值加1,加1后的值作为当前表达式的值;所以输出为x=5,y=6。z++;和++z;都是独立的语句,都是完成加1的操作,所以在第二个输出语句中输出时x、y各做一次加1操作,z做了两次加1操作。
【例2.7】 若有变量定义int x=6;,则下面语句的运行结果是_______。
printf("x1=%d,x2=%d\n",++x,x++);
A.x1=7,x2=7 B.x1=8,x2=6 C.x1=8,x2=8 D.x1=7,x2=8
解题知识点:自增/自减运算符;系统对函数参数的求值顺序。
解:答案为B。本题的解题要点是:在Turbo C中系统对函数参数的求值顺序是自右而左。printf中要输出两个表达式的值(++x和x++),先求右边的表达式x++的值为6(先使用当前值,后加1),x自增1为7;再求左边的表达式++x的值为8(先加1,再使用),所以输出x1=8,x2=6。可能出现的错误是从左到右计算表达式而选择选项A。
【例2.8】 在下列选项中,不合法的赋值语句是_______。
A.n1=n2=n3=0; B.k=i==j; C.k=i&&j; D.a=b+c=1;
解题知识点:赋值语句的书写规则。
解:答案为D。选项A相当于n3=0;n2=n3;n1=n2;,所以合法;选项B相当于k=(i==j);,即赋值号右侧是关系表达式,当i和j相等时,k赋值为1,否则k赋值为0,合法;选项C中赋值号右侧是逻辑表达式,当i和j均非零时k赋值为1,否则k赋值为0,也合法;选项D相当于a=((b+c)=1);,可见右边的赋值号的左侧不是变量名,而是表达式,所以不合法。
【例2.9】 设有如下表达式:
<<◆◆◆>c+d||~c&d
则表达式中运算符的优先顺序是_______。
A.~、+、<<、>、&、|| B.~、+、>、<<、&、||
C.~、+、<<、&、>、|| D.~、+、&、||、>、<<
解题知识点:位运算及其优先级。
解:答案为A。优先级顺序是:单目运算符“~”优先级最高,然后依次是算术运算符“+”、移位运算符“<<”、关系运算符“>”、按位与运算符“&”,最后是逻辑运算符“||”。
【例2.10】 设有如下定义:
unsigned x=0x6937;
int n=8;
则表达式(x&~(~0<<n))的作用是_____。
A.x左移8位 B.对x的低位字节清零
C.对x的高位字节置1 D.对x的高位字节清零,保留低位字节
解题知识点:位运算及其优先级。
解:答案为D。因为x是无符号整型,占16个二进位,~(~0<<8)为0000000011111111,由于与0相与对应位被清零,与1相与保留对应位,所以x的高位字节被清零,低位字节被保留。
【例2.11】 已知小写字母a的ASCII码值为97,有如下程序:
则运行结果是_______。
A.a B.b C.d D.100
解题知识点:按位或运算;字符的存储形式。
解:答案为C。本题的解题要点是:先将操作数转换成二进制,再进行按位或运算,结果作为一个字符的ASCII码值,输出对应的字符。a和b用二进制数表示分别为:a=00100000,b=01000100。a|b=01100100转换为十进制是100,ASCII码值100对应的字符是小写字母d。
【例2.12】 以下叙述中不正确的是_______。
A.表达式a&=b等价于a=a&b B.表达式a<<=b等价于a=a<<b
C.表达式a%=b等价于a=a%b D.表达式a!=b等价于a=a!b
解题知识点:复合运算符。
解:答案为D。本题的解题要点是:只有算术运算符和位运算符中的双目运算符才可以和赋值运算符组成复合赋值运算符。“&”、“<<”、“%”可以和“=”组成复合赋值运算符,但是“!”是逻辑非运算符,是单目运算符,不能与赋值运算符组合。而“!=”是关系运算符,含义是不等于,是不可分割的一个整体。
【例2.13】 已知大写字母A的ASCII码值为65,设有如下程序:
void main()
{char c='A';int b=-8;
printf("%d\n",c^b>>2);
}
则运行结果是_______。
A.-18 B.-65 C.65 D.57
解题知识点:按位异或运算、右移运算及其优先级。
解:答案为B。本题解题要点:①注意“>>”的优先级高于“^”;②在Turbo C中右移位采用的是算术移位;③若位运算的两个操作数长度不同,应先以长的为基准,右端对齐,短的是正数则左边补0,是负数则左边补1,然后再运算。先将b转换成二进制为1111111111111000,计算b>>2得1111111111111110;字符'A'的二进制形式为01000001,高8位补0后,再与b作异或运算得1111111110111110;最高位为1是负数,转换成原码为1000000001000001,转换成十进制数为-65。可能出现的错误是优先级搞错,若先做异或运算后做右移位,则会选择选项A。
2.3 同步练习
一、选择题
1.在C语言中,int、char、short三种类型的数据所占用的内存_______。
A.均为2字节 B.由用户自定义
C.由所用机器的机器字长决定 D.是任意的
2.设int类型的数据占2个字节,则unsigned int类型数据的取值范围是_______。
A.0~255 B.0~65535
C.-32768~32767 D.-256~255
3.以下_______是不正确的转义字符。
A.'\\' B.'\'' C.'\08a' D.'\0'
4.设有说明语句:char a='\72';,则变量a_______。
A.包含1个字符 B.包含2个字符 C.包含3个字符 D.说明不合法
5.在C语言中,char型数据在内存中是以_______形式存储的。
A.原码 B.补码C.AS C.I码 D.反码
6.以下选项中合法的字符常量是_______。
A."B" B.'\010' C.68 D.D
7.在C语言中,要求操作数必须是整型的运算符是_______。
A.% B./ C.< D.!
8.以下的选择中,正确的赋值语句是_______。
A.a=1,b=2; B.i++; C.a+b=5; D.y=int(x);
9.以下不正确的叙述是_______。
A.在C程序中所有的变量必须先定义后使用
B.在程序中,APH和aph是两个不同的变量
C.若a和b类型相同,执行a=b;后b中的值放入a中,b中的值不变
D.当输入数据时,对整型变量只能输入整型值,对实型变量只能输入实型值
10.若变量已正确定义并赋值,下面符合C语言语法的表达式是_______。
A.a:=b+1 B.a=b=c+2 C.int 18.5%3 D.a=a+7=c+b
11.若x为int型变量,则执行以下语句后,x的值为_______。
x=6;x+=x-=x*x;
A.36 B.–60 C.60 D.–24
12.若有定义int x;,则逗号表达式(x=4*5,x*5),x+25的结果为(1),x的值为(2)。
(1)A.20 B.100 C.表达式不合法 D.45
(2)A.20 B.100 C.125 D.45
13.若已定义x和y是double类型,则表达式x=1,y=x+3/2的值是_______。
A.1 B.2 C.2.0 D.2.5
14.设x和y均为int型变量,则执行以下语句后的结果为_______。
x=15;y=5;printf("%d\n",x%=(y%=2));
A.0 B.1 C.6 D.12
15.若有以下程序段:
int c1=1,c2=2,c3;
c3=1.0/c2*c1;
则执行后,c3的值是_______。
A.0 B.0.5 C.1 D.2
16.若x、y、z均为int型变量,m为long型变量,则在16位PC上执行下述语句后,y值的十六进制形式为(1),x值为(2),z值为(3),m值为(4)。
y=(x=32767,x+1);z=m=0xFFFF;
(1)A.FFFF B.7FFF C.7FFE D.8000
(2)A.-32768 B.0 C.32768 D.32767
(3)A.0 B.32768 C.-1 D.65535
(4)A.0 B.32768 C.-1 D.65535
17.以下叙述不正确的是_______。
A.一个好的程序应该有详尽的注释
B.C程序中的#include和#define均不是C语句
C.在C程序中,赋值运算符的优先级最低
D.在C程序中,j++;是一条赋值语句
18.若有,其错误的C语言表达式是_______。
A.a*e/b*c B.a/b/c*e C.a*e/b/c D.(a*e)/(b*c)
19.设a和b均为int型变量,且a值为15,b值为240,则表达式(a&b)&&b的结果为_______。
A.0 B.1 C.true D.false
20.在位运算中,操作数每右移一位,其结果相当于_______。
A.操作数乘2 B.操作数除以2
C.操作数除以16 D.操作数乘以16
21.若有以下定义和语句,则执行语句后a和b的值分别是_______。
int a=3,b=4;
a=a^b;b=b^a;a=a^b;
A.a=3,b=4 B.a=4,b=3 C.a=3,b=3 D.a=4,b=4
22.设有以下语句,则c的二进制值是_______。
char a=3,b=6,c;
c=a^b<<2;
A.00011011 B.00010100 C.00011100 D.00011000
23.已知char a=15,则~a、-a和!a的整数值分别为_______。
A.240、-15、0 B.0、-15、240 C.-16、-15、0 D.0、-15、0
二、填空题
1.字符常量'a'在内存中应占(1)字节,字符串"a"应占(2)字节。
2.在16位PC环境下,int类型数据应占(1)字节,short类型数据应占(2)字节,long类型数据应占(3)字节,double类型数据应占(4)字节。
3.在16位PC环境下,short类型数据的取值范围是(1),unsigned int类型数据的取值范围是(2)。
4.若采用十进制数的表示方法,则077是(1),0111是(2),0x29是(3),0xAB是(4)。
5.若有说明char s1='\077',s2='\'';,则s1中包含(1)个字符,s2中包含(2)个字符。
6.设x为float型变量,y为double型变量,a为int型变量,b为long型变量,c为char型变量,则表达式x+y*a/x+b/y+c的结果为_______类型。
7.定义如下变量:
float x=2.5,y=4.7;int a=7;
表达式x+a%3*(int)(x+y)%2/4的值为_______。
8.设a,c,x,y,z均为int型变量,在下面对应的横线上写出各表达式的结果。
(1)a=(c=5,c+5,c/2)(1)
(2)x=(y=(z=6)+2)/5(2)
(3)18+(x=4)*3(3)
9.下列程序的运行结果为_______。
10.下列程序的运行结果是_______。
11.写出实现以下计算的C语言赋值语句_______。
12.下列程序的运行结果为_______。
13.下列程序的运行结果为_______。
14.下列程序的运行结果为_______。
15.下列程序的运行结果为_______。
16.表达式5&7的值为(1),5|7的值为(2),5^7的值为(3)。
17.二进制数a值为00101101,若想通过异或运算a^b使a的高4位取反,低4位不变,则二进制数b值为_______。
18.二进制数a值为01100101,若想通过a&b运算使a的低4位清零,高4位不变,则二进制数b值为_______。
19.在C语言中,“&”作为双目运算符时表示的是(1),而作为单目运算符时表示的是(2)。
2.4 参考答案
一、选择题
1.C 2.B 3.C 4.A 5.C
6.B 7.A 8.B 9.D 10.B
11.B 12.(1)D (2)A 13.C 14.A 15.A
16.(1)D (2)D (3)C (4)D 17.C 18.A 19.A
20.B 21.B 22.A 23.C
二、填空题
1.(1)1 (2)2
2.(1)2 (2)2 (3)4 (4)8
3.(1)–32768~32767 (2)0~65535
4.(1)63 (2)73 (3)41 (4)171
5.(1)1 (2)1
6.double
7.2.5
8.(1)2 (2)1 (3)30
9.11,1,0,1
10.a=A,b=d,c=D
11.z=sin(75*3.14/180)/(x*y)
12.65535
13.dqz
14.14,a=9
15.24,20,36
16.(1)5 (2)7 (3)2
17.11110000
18.11110000
19.(1)按位与 (2)取地址