《C语言程序设计》基本知识点解答二.docx
《《C语言程序设计》基本知识点解答二.docx》由会员分享,可在线阅读,更多相关《《C语言程序设计》基本知识点解答二.docx(27页珍藏版)》请在冰豆网上搜索。
《C语言程序设计》基本知识点解答二
C语言程序设计基本知识点解答
(二)
第三章数据类型、运算符和表达式
Q051什么是“数据类型”?
(数据类型)
A051数据类型就是指数据在计算机中保存和运算时的组织和形式。
实际问题当中本来就有若干种不同类型的数据,因此用来解决这些实际问题的计算机编程语言中自然应该有对应的数据类型来描述这些数据。
比如最基本的数据类型就是整数、实数,另外还有非数值型的数据类型,如字符串。
一个计算机程序中用到的所有数据都必须具有某种类型。
Q052什么是“运算符”?
(运算符)
A052运算符是指一些具有规定运算功能的特定的符号。
如+、-、*、/、%等等。
这里的运算功能可能是我们比较熟悉的运算比如算术运算(加减乘除)、逻辑运算(与或非)或比较运算(大于小于等于),也可能是其他一些在计算机语言当中特有的运算如加1减1运算、位运算等等。
C语言共有34种运算符。
Q053什么是“表达式”?
(表达式)(优先级)(结合性)
A053表达式是按照运算符的性质,用运算符把数据连接起来以达到数据运算目的而构成的式子。
写表达式的最终目的是要进行计算它求出它的值。
求解表达式的过程是由计算机完成的,因此,要想得到正确的结果,就必须写出正确的表达式。
而一个表达式中往往包含多个运算符,所以必须熟悉每一种运算符的性质(优先级别和结合性),才能写出有正确求解结果的表达式。
Q054C语言有哪些数据类型?
(数据类型)
A054C语言中的所以数据类型如下图所示:
Q055什么是“常量”?
(常量)
A055程序运行期间,值不能被改变的量称为常量。
如果试图去改变常量的值,就肯定会出错。
在C语言中,至少有两种方法表示一个常量,即“直接常量”和“符号常量”。
Q056什么是“直接常量”?
(常量)
A056直接常量也叫字面常量,就是一看就知道的、直接具有具体的固定的值的量。
比如1、2、3;0.1、10.0;‘a’,‘1’;“hello”等。
常量也是有类型的。
前面所列举的常量就分别是整型、实型、字符型和字符串型的常量。
Q057什么是“符号常量”?
(常量)(符号常量)
A057直接常量的好处是一看就知道的它的值,但是缺点是读程序的人无法方便的知道这个值到底代表什么含义,即这个值传达的信息是不完整不明确的。
这样的数常常被称之为“幻数(MagicNumber)”。
如果我们可以给这些数值起一个有意义有具体含义的名字就可以解决这个问题了。
符号常量的目的就在此。
它是用一些符号来代替程序当中出现的常量。
从而使得程序的可读性和可维护性大大增强。
Q058C语言中,如何实现“符号常量”?
(常量)(符号常量)
A058C语言中,可以使用#define预处理命令来实现符号常量。
例如下面的程序:
#definePI3.14159
intmain()
{
floatr,c,s,v;r=2;
printf("PI=%f\n",PI);
c=2*PI*r;printf("周长=%f\n",c);
s=PI*r*r;printf("面积=%f\n",s);
v=4*PI*r*r*r/3;printf("体积=%f\n",v);
return0;
}
第一步,程序第一行用#define预处理命令定义了一个符号常量,其名字是PI,代表的常量值是3.14159。
第二步,在本程序以下的代码中,凡是原来直接出现3.14159的地方,全部换成符号PI。
这样修改后程序运行的结果和直接使用字面常量是一样的。
Q059用#define实现符号常量的原理是什么?
(符号常量)(define)
A059实际上是一个在预处理阶段的替换过程。
在前述问题的程序中,第一行的含义就是定义了一个符号名字叫做PI,它代替的一串字符是3.14159。
然后,在对这个程序进行编译时,编译器首先启动预编译器(preprocessor)对源程序进行预编译处理。
当预编译器发现程序中有诸如#define这样的预编译命令时,就对它们进行相应命令指定的处理。
比如,对于#define预编译命令,预编译器就扫描整个源程序代码,将其中所有出现的由#define定义的符号全部替换成在#define命令行定义的符号后出现的字符串。
因此,上述程序在预编译处理后,就变成了
intmain()
{
floatr,c,s,v;r=2;
printf("PI=%f\n",3.14159);
c=2*3.14159*r;printf("周长=%f\n",c);
s=3.14159*r*r;printf("面积=%f\n",s);
v=4*3.14159*r*r*r/3;printf("体积=%f\n",v);
return0;
}
因此就如同直接使用字面常量一样了。
Q060使用“符号常量”的好处是什么?
(符号常量)
A060两个主要的好处:
(1)从所起的符号名字中可以清楚地看出该常量的含义,从而做到“见名知意”,避免“幻数”。
比如上述程序中阅读此程序的人很容易的由符号名PI知道这个常量的含义就是圆周率。
当然要想达到这样的效果,前提是所起符号名称必须和实际含义相符合。
因为符号是可以任意命名的,你完全可以用这样的#define命令#definePRICE3.14159来定义一个符号PRICE代替3.14159,但是这样作就失去符号常量的存在意义了。
(2)在需要修改常量的值时可以做到“一改全改”,减少工作量。
如果一个常量的值发生了变化,如果原来是用直接常量实现的,那么很显然程序的修改工作量就很大,尤其是当这个常量出现次数很多的时候。
但是,如果用符号常量来实现的话,那么只需要改动一个地方,就是#define命令这个地方,而程序其它部分完全不需改动,因为在进行预编译时新的常量值会被正确的替换进去。
Q061为什么在Q058的程序中,第5行的第一个PI没有被替换成3.14159?
(符号常量)
A061在预编译器对源程序代码当中出现的符号常量进行替换时,并不是凡是发现有相同的符号名就无条件替换。
至少有两种情况下,这个替换不会发生:
第一:
这个符号出现在双引号当中。
双引号括起来的叫做字符串常量,要的就是其中包含的原义字符,所以不会被替换;
第二:
这个符号不是单独且完整出现的,而是另一个符号的一部分。
比如,定义了符号常量PI,那么代码中如果有另一个符号叫API,,那么替换不会发生,即不会变成A3.14159。
Q062什么是“预编译”?
(预编译)
A062预编译也叫编译预处理:
是指在对源程序进行正式编译之前所作的一些处理。
这些处理是由预处理命令指定的。
源程序经过预处理后,再由编译程序进行正式的编译。
预处理命令虽然用在C程序中,但它并不是C语言本身的组成部分,不能用C编译器直接对它进行编译,必须由预编译器来处理。
预处理命令都是以符号“#”开头的。
Q063什么是“变量”?
(变量)
A063程序运行期间,值可以被改变的量称为变量。
C程序允许把数值存放在变量中,每个变量都由一个变量名来标识。
每个变量都必须有一个变量类型。
每个变量根据它的类型不同,在内存中占据一定数目的字节单元,该变量的值就存放在这些内存单元中。
Q064“变量”的本质是什么?
(变量)
A064变量的本质就是命名的内存单元,因此它的值可以被改变。
所谓改变变量的值实际上是改变变量所占内存单元中的内容,因为变量名和内存单元的地址、变量值和内存单元的内容是相对应的。
如图所示:
Q065变量的名字是否可以随意命名?
(变量)
A065当然不是。
任何计算机编程语言中,关于标志符号的命名总是有规定的。
变量名就属于标志符的一种,其它的标志符还有符号常量名、数组名、函数名、构造类型名等等。
C语言中,变量(标识符)的命名规定是:
▪只能由大小写字母、下划线和数字组成;
▪开头的第一个字符只能是大小写字母或下划线;
▪大小写是敏感的;
▪不能与C语言中的关键字重复;
▪名字在其作用范围内必须是唯一的;
▪名字的长度不能超过系统的规定。
具体的长度限制随系统不同而不同。
Q066在A065中提到的“关键字”是什么?
(关键字)
A066关键字(Keyword),也叫保留字(Reserveword),是计算机语言当中具有预先固定的命名的、能完成指定功能的符号。
一种编程语言的很大一部分功能就是由关键字来完成的。
C语言一共有32个关键字。
其中,部分是用于定义变量类型的,如int、long、float、char等,部分是用于实现基本程序结构的,如if、switch、while、for等。
可以这么说,关键字+运算符就等于一门语言的绝大部分功能。
Q067我听别人说过“好的变量名”,这是指什么?
(变量名)
A067理论上将,变量命名只要满足上述规定,任何名字都是可以的。
但是,在给变量命名时,除了规定之外,还有一个良好的命名习惯的问题。
即是说,首先要起合法的名字,其次要起好的名字。
所谓好的变量名,最主要的要求就是要“见名知意”。
别人通过变量的名字就可知道这个变量所保存信息的含义,这有助于增强程序的可读性。
关于命名习惯,有如下建议:
▪避免使用无意义的名字,应严格做到“见名知意”;
▪尽量使用代表变量实际含义的英文单词或缩写作标识符名;
▪当名字包含多个单词时,通常使每个单词的首字母大写;
▪不使用以下划线开头的名字,因为这样的名字通常是系统内部保留的标识符名;
▪在整个程序中尽量保持统一的命名方式。
Q068在编译程序时,提示有错,错误为“Error:
Undefinedsymbol?
?
”,这是什么原因?
(变量)(定义变量)
A068“Undefinedsymbol”的意思是“为定义的符号”,就是说程序当中存在着还没有定义就直接使用的变量。
这是因为C语言语法上要求,任何一个变量在使用之前必须先定义它。
所谓定义一个变量,就是要在该变量被使用之前,告知编译器该变量的名字、类型和存储类别,这样编译器才能正确编译
Q069那么,如何定义变量?
(定义变量)
A069变量定义具有三个目的:
⑴定义变量名;⑵定义变量类型;⑶向程序员描述该变量。
变量定义的一般格式是:
typename;/*comment*/
类型名字;/*注释*/
例如:
intage;/*theageofstudent*/
floatscore;/*thescoreofstudent*/
floataverage;/*theaverageofscore*/
longnumber;/*thenumberofstudent*/
doubledistance;/*betweenearth&moon*/
charUserSelection;/*keyuserhit*/
在程序运行时,系统将根据变量的定义为其分配相应大小的内存单元。
Q070为什么在C语言中,整数017和17并不是相同的?
(整型)
A070这是因为在C语言中,17是十进制的整数,而017是八进制整数,相当于十进制的15。
C语言中对于同一个整型常量,可以有三种不同的形式来表示,即分别用十进制、八进制、十六进制来表示同一个数。
为了区分不同进制的整型常量,也为了和其它的标志符区分,C语言中规定,以数字“0”开头的整型常量是八进制的,而以“0x”开头的整型常量的整型是十六进制的。
比如十进制整数18,就等价与八进制整数022,也等价与十六进制整数0x12。
Q071在C语言中,整型变量是如何分类的?
(整型)
A071在C语言中,整型变量分为两大类:
有符号整型和无符号整型。
而不管是有符号还是无符号整型变量,又都分为基本整型、短整型和长整型三种。
分类情况如下表所示:
类型
关键字
占字节数目
(TurboC)
有符号signed
基本整型
signedint
2字节
短整型
signedshortint
(signedshort)
2字节
长整型
signedlongint
(signedlong)
4字节
无符号unsigned
基本整型
unsignedint
2字节
短整型
unsignedshortint
(unsignedshort)
2字节
长整型
unsignedlongint
(unsignedlong)
4字节
其中,有符号整型变量中,关键字signed可以省略。
Q072为什么C语言中,整型变量要分很多种?
(整型)
A072一方面是因为实际问题当中的数据本来就是具有不同的类型的,更主要的是因为这些数据的变化范围是不同的。
不同范围的数据所需要的内存存储单元也是不一样的。
因此,必须根据数据的范围来决定给它分配多大的存储空间,而不致发生空间不够或空间浪费的问题。
这就好比学校的教学楼里,既有大教室,也有小教室,然后根据来上课的人数分配合适的教室。
而不是全部都是大教室,那样就会产生教室不足或教室浪费的问题。
C语言提供了多种整型数据类型,不同类型的整型数据占有的字节单元数目是不同的,所以不同类型的整型数据可表示的数的范围也是不同的,这样有助于根据实际数据的最大值来确定其最合适的类型。
Q073那么,到底每种整型变量能保存的数据范围是多少呢?
(整型)
A073由于每一种整型数据占有的字节单元数目都是有限的,所以每一种整型数据可表示的数的范围也是有限的。
ANSIC标准定义的整型类型的表示范围如下表所示:
类型
字节数
有效表示范围
[signed]int
2字节
-32768~+32767
unsignedint
2字节
0~+65535
[signed]short[int]
2字节
-32768~+32767
unsignedshort[int]
2字节
0~+65535
[signed]long[int]
4字节
-2147483648~+2147483647
unsignedlong[int]
4字节
0~+4294967295
Q074有符号和无符号的区别是什么?
(整型)
A074有符号和无符号的区别关键在于变量所占字节单元中“最高位”的性质。
●对于有符号变量:
把最高位作为符号位保存数据的符号(0为正,1为负),其余位保存具体数值,因此可以用于正确保存限值范围内的正数或负数。
比如有inta;那么a的有效数值保存范围为-32768~32767。
●对于无符号变量:
最高位不作为符号位,全部的位都用来保存数据的数值,因此可以用于正确保存限值范围内的正数。
比如有unsignedintb;那么b的有效数值范围为0~65535。
Q075为什么下面的程序中,输出的结果是over=-32768,而不是期望的over=32768?
(整型)
voidmain()
{
intmax,over;
max=32767;over=max+1;
printf("over=%d",over);
}
A075因为发生了整型数据的“溢出”问题。
前面已经说过,由于每一种整型数据占有的字节单元数目都是有限的,所以每一种整型数据可表示的数的范围也是有限的。
程序中,max是int有符号基本整型的变量,所以其有效的数据保存范围就是-32768~+32767。
当max等于32767时,实际其所占两个字节中的情况如图所示:
max+1后赋值给同样的int有符号基本整型的变量over,则over中实际其所占两个字节中的情况如图所示,很显然已经变成了-32768的补码了。
所以用printf函数按照%d格式显示出来就是-32768。
Q076那怎样才不会出现“整型数据溢出”的问题呢?
(整型)
A076解决的方法就是,在定义变量时一定要指定合适的类型,保证它所保存的数据在整个程序运行过程中不会超出其能够有效表示的范围。
比如,上面的程序中,如果把over定义成unsignedint或long型的变量就可以避免“溢出”的问题。
Q077实型变量是如何分类的?
(实型)
A077实型变量的分类如下表所示:
类型
单精度
双精度
关键字
float
double
字节数
4字节
8字节
有效数字位数
6~7位
15~16位
数值范围
10-37~10+38
10-307~10+308
很明显,由于不同的实型数据是用不同数目的有限字节单元保存的,所以它们能表示的数值范围是不同的,能保留的有效数字位数也是不同而且是有限的。
Q078实型数据在内存中是如何存储的?
(实型)
A078实型数据在内存中是以“尾数”和“阶码”的形式存放的。
即在一个实型数据(浮点数)所占字节单元中,一部分位用来保存阶码,一部分位用来保存尾数。
如图所示:
不同的编译系统位数分配不同。
总之,尾数部分位数越多,可以表示的数的有效数字位数就越多,精度就越高;阶码部分位数越多,可以表示的数的范围就越大。
Q079什么是字符型常量?
(字符型)
A079C的字符常量是用单引号(')括起来的一个字符。
比如:
'a'、'A'、'd'、'D'、'?
'、'%'、'$'、'2'、'4'等等。
注意两点:
第一,必须是单引号,第二,单引号里只能有一个字符。
Q080为什么字符常量要用单引号括起来?
(字符型)
A080这是为了和程序中其它类型的数据区分开来。
比如字符常量'A',如果不加单引号,只是一个A,那么一定会被编译器认为成一个符号的名字比如变量名。
又比如字符常量'1',如果不加单引号,只是一个1,那么一定会被编译器认为成是一个整型常量1。
因此,必须在所需要的字符周围加上一些称之为“界定符”的字符把它们包围起来,才能和其它数据进行区分。
Q081既然单引号里只能有一个字符,为什么有的程序中会出现'\n','\101'这样的字符?
(字符型)
A081这是因为除了前面提到的“单引号括起来的一个字符”形式的字符常量,C语言还存在另一种形式的特殊的字符常量,叫“转义字符常量”。
它是用单引号括起来的以一个“\”字符开头的规定的字符序列。
比如问题当中提到的'\n','\101'。
在转义字符常量中,单引号里面的确是不止一个字符,但实际上整个还是只代表一个字符,也是合法的字符常量。
这也就是“转义”之含义。
起到转义作用的是单引号当中的“\”,它被用来作为转义字符序列的起始字符。
如果单引号中起始字符不是“\”,又多于一个字符,那么就不是合法的字符常量了。
比如,'nn','101'就不是合法的字符常量。
Q082为什么要用到“转义字符常量”?
(字符型)(转义字符常量)
A082因为除了键盘上的所有字符外,程序当中还需要用到一些在键盘上找不到也就无法直接输入的特殊字符。
这些字符往往代表了一些独特的特定的功能。
因此需要用一种特殊的方法来表示它们,这就产生了“转义字符常量”,也叫“转义字符序列”。
Q083C语言中都支持哪些“转义字符常量”?
(字符型)
A083C语言所支持的转义字符常量如可以分为三大类,如下表所示:
Q084上表中出现的ASCII代码是什么意思?
(字符型)(ASCII码)
A084ASCII是英文AmericanStandardCodeforInformationInterchange的缩写,其中文含义是“美国信息交换标准代码”。
实际上,ASCII码是一个0~255之间的整数。
每一个整数对应着一个不同的字符,即每一个字符都有一个不同的整数代码。
比如,上表中出现的字符'\n'用整数10代表,而单引号本身是用整数39代表的。
完整的ASCII码表请参见课本374页。
Q085为什么每一个字符要用一个不同的整数来代表?
(字符型)(ASCII码)
A085根本原因在于计算机的基本原理是二进制的。
字符型的数据本身是非数值型的,是无法保存在计算机当中的,因为计算机中所有的数据最终都要以二进制数的形式来保存。
因此,就要设法将非数值型的数据转换为数值型的数据,从而产生了很多种称之为“字符集”的东西。
在各种“字符集”中,把每一个字符用一个唯一的整数来代表。
当程序运行时,在出现在该字符的地方实际内存中存储的是该字符对应的整数代码。
ASCII就是一种扩充的西文字符集,它把常用的256个字符分别用0~255之间的整数来代表。
Q086那么说,C语言中的字符型数据实际上就相当于数值型的数据喽?
(字符型)
A086正是。
每个字符型数据无论是常量还是变量在内存中只占一个字节,这个字节中实际保存的就是该字符的ASCII代码。
而ASCII码是一个整数,就要按整数的存储方式来保存,因此在C语言中,字符型和整型数据的存储方式是一致的,不同的只是两者占据的字节单元数目。
比如字符常量'A',它的ASCII码是整数65,因此在内存中,字符常量'A'所占的一个字节中实际保存的是整数65,即01000001。
反过来看,如果我只知道有一个字节中存放的是01000001,那么我们既可以说它是整数65,也可以说它是字符常量'A'。
可见,在C语言中,字符型数据和整型数据在一定范围内是通用的,即两者可以相互赋值,相互输出,也可以在一起进行运算。
Q087请举例说明字符型数据和整型数据在一定范围内是通用的?
(字符型)
A087程序如下:
#include
voidmain()
{
charc1,c2,c3;
c1='A';c2='b';c3='';/*c3保存的是字符空格,ASCII码是32*/
c1=c1+32;/*字符可以和整数进行算术运算*/
c2=c2-c3;/*字符甚至还可以和字符进行算术运算*/
printf("c1=%c,c1=%d\n",c1,c1);/*输出结果时,字符既可以显示为字符(%c)*/
printf("c2=%c,c2=%d\n",c2,c2);/*也可以显示整数(%d)*/
return;
}
实际上,无论是字符和整数的运算,还是字符和字符的运算,本质上都是整数之间的运算。
因此上述程序的运行结果就是:
c1=a,c1=97
c2=B,c2=66
Q088这么多字符的ASCII码,如何记住它们?
(字符型)(ASCII码)
A088根本不需要记住它们,因为你随时都可以查阅ASCII码表得到所需字符的ASCII码。
但是,对其中最常用的一些字符,你只需记住它们在ASCII码表中出现的简单规律,就可以记住它们的ASCII码。
常用字符及对应ASCII码如下表所示:
仔细观察上表,发现规律没有?
规律①:
字符'0'的ASCII码是48,字符'0'到字符'9'的ASCII码是连续的;
规律②:
字符'A'的ASCII码是65,字符'A'到字符'Z'的ASCII码是连续的;
规律③:
字符'a'的ASCII码是97,字符'a'到字符'z'的ASCII码是连续的;
规律④:
对应大小写字母的ASCII码之差等于32。
Q089为什么'0'-0不等于0?
(ASCII码)(字符常量)
A089因为'0'是字符型的常量,它实际上相当