1、 什么是“符号常量”?(常量)(符号常量)A057 直接常量的好处是一看就知道的它的值,但是缺点是读程序的人无法方便的知道这个值到底代表什么含义,即这个值传达的信息是不完整不明确的。这样的数常常被称之为“幻数(Magic Number)”。如果我们可以给这些数值起一个有意义有具体含义的名字就可以解决这个问题了。符号常量的目的就在此。它是用一些符号来代替程序当中出现的常量。从而使得程序的可读性和可维护性大大增强。Q058 C语言中,如何实现“符号常量”?A058 C语言中,可以使用 #define 预处理命令来实现符号常量。例如下面的程序:#define PI 3.14159int main()
2、 float r, c, s, v; r=2;printf(PI =%fn, PI); c=2* PI *r; printf(周长 =%fn, c); s= PI *r*r;面积 =%fn, s); v=4* PI *r*r*r/3;体积 =%fn, v); return0;第一步,程序第一行用 #define 预处理命令定义了一个符号常量,其名字是PI,代表的常量值是3.14159。第二步,在本程序以下的代码中,凡是原来直接出现3.14159的地方,全部换成符号PI。这样修改后程序运行的结果和直接使用字面常量是一样的。Q059 用 #define 实现符号常量的原理是什么?(符号常量)(de
3、fine)A059 实际上是一个在预处理阶段的替换过程。在前述问题的程序中,第一行的含义就是定义了一个符号名字叫做PI,它代替的一串字符是3.14159。然后,在对这个程序进行编译时,编译器首先启动预编译器(preprocessor)对源程序进行预编译处理。当预编译器发现程序中有诸如#define这样的预编译命令时,就对它们进行相应命令指定的处理。比如,对于#define预编译命令,预编译器就扫描整个源程序代码,将其中所有出现的由#define定义的符号全部替换成在#define命令行定义的符号后出现的字符串。因此,上述程序在预编译处理后,就变成了, 3.14159); c=2*3.14159
4、 *r;周长=%fn s=3.14159 *r*r;面积=%fn v=4*3.14159 *r*r*r/3;体积=%fn因此就如同直接使用字面常量一样了。Q060 使用“符号常量”的好处是什么?(符号常量)A060 两个主要的好处:(1) 从所起的符号名字中可以清楚地看出该常量的含义,从而做到“见名知意”,避免“幻数”。比如上述程序中阅读此程序的人很容易的由符号名PI知道这个常量的含义就是圆周率。当然要想达到这样的效果,前提是所起符号名称必须和实际含义相符合。因为符号是可以任意命名的,你完全可以用这样的#define命令 #define PRICE 3.14159来定义一个符号PRICE代替3
5、.14159,但是这样作就失去符号常量的存在意义了。(2) 在需要修改常量的值时可以做到“一改全改”,减少工作量。如果一个常量的值发生了变化,如果原来是用直接常量实现的,那么很显然程序的修改工作量就很大,尤其是当这个常量出现次数很多的时候。但是,如果用符号常量来实现的话,那么只需要改动一个地方,就是#define命令这个地方,而程序其它部分完全不需改动,因为在进行预编译时新的常量值会被正确的替换进去。Q061 为什么在Q058的程序中,第5行的第一个PI没有被替换成3.14159?A061 在预编译器对源程序代码当中出现的符号常量进行替换时,并不是凡是发现有相同的符号名就无条件替换。至少有两种
6、情况下,这个替换不会发生:第一:这个符号出现在双引号当中。双引号括起来的叫做字符串常量,要的就是其中包含的原义字符,所以不会被替换;第二:这个符号不是单独且完整出现的,而是另一个符号的一部分。比如,定义了符号常量PI,那么代码中如果有另一个符号叫API,那么替换不会发生,即不会变成A3.14159。Q062 什么是“预编译”?(预编译)A062 预编译也叫编译预处理:是指在对源程序进行正式编译之前所作的一些处理。这些处理是由预处理命令指定的。源程序经过预处理后,再由编译程序进行正式的编译。预处理命令虽然用在C程序中,但它并不是语言本身的组成部分,不能用C编译器直接对它进行编译,必须由预编译器来
7、处理。预处理命令都是以符号“#”开头的。Q063 什么是“变量”?(变量)A063 程序运行期间,值可以被改变的量称为变量。C程序允许把数值存放在变量中,每个变量都由一个变量名来标识。每个变量都必须有一个变量类型。每个变量根据它的类型不同,在内存中占据一定数目的字节单元,该变量的值就存放在这些内存单元中。Q064“变量”的本质是什么?A064变量的本质就是命名的内存单元,因此它的值可以被改变。所谓改变变量的值实际上是改变变量所占内存单元中的内容,因为变量名和内存单元的地址、变量值和内存单元的内容是相对应的。如图所示:Q065 变量的名字是否可以随意命名?A065当然不是。任何计算机编程语言中,
8、关于标志符号的命名总是有规定的。变量名就属于标志符的一种,其它的标志符还有符号常量名、数组名、函数名、构造类型名等等。C语言中,变量(标识符)的命名规定是: 只能由大小写字母、下划线和数字组成; 开头的第一个字符只能是大小写字母或下划线; 大小写是敏感的; 不能与C语言中的关键字重复; 名字在其作用范围内必须是唯一的; 名字的长度不能超过系统的规定。具体的长度限制随系统不同而不同。Q066 在A065中提到的“关键字”是什么?(关键字)A066关键字(Keyword),也叫保留字(Reserve word),是计算机语言当中具有预先固定的命名的、能完成指定功能的符号。一种编程语言的很大一部分功
9、能就是由关键字来完成的。C语言一共有32个关键字。其中,部分是用于定义变量类型的,如int、long、float、char等,部分是用于实现基本程序结构的,如if、switch、while、for等。可以这么说,关键字运算符就等于一门语言的绝大部分功能。Q067 我听别人说过“好的变量名”,这是指什么?(变量名)A067 理论上将,变量命名只要满足上述规定,任何名字都是可以的。但是,在给变量命名时,除了规定之外,还有一个良好的命名习惯的问题。即是说,首先要起合法的名字,其次要起好的名字。所谓好的变量名,最主要的要求就是要“见名知意”。别人通过变量的名字就可知道这个变量所保存信息的含义,这有助于
10、增强程序的可读性。关于命名习惯,有如下建议: 避免使用无意义的名字,应严格做到“见名知意”; 尽量使用代表变量实际含义的英文单词或缩写作标识符名; 当名字包含多个单词时,通常使每个单词的首字母大写; 不使用以下划线开头的名字,因为这样的名字通常是系统内部保留的标识符名; 在整个程序中尽量保持统一的命名方式。Q068 在编译程序时,提示有错,错误为“Error:Undefined symbol ??”,这是什么原因?(变量)(定义变量)A068“Undefined symbol”的意思是“为定义的符号”,就是说程序当中存在着还没有定义就直接使用的变量。这是因为C语言语法上要求,任何一个变量在使用
11、之前必须先定义它。所谓定义一个变量,就是要在该变量被使用之前,告知编译器该变量的名字、类型和存储类别,这样编译器才能正确编译Q069 那么,如何定义变量?(定义变量)A069变量定义具有三个目的:定义变量名;定义变量类型;向程序员描述该变量。变量定义的一般格式是:type name; /*comment */类型 名字; /* 注释*/例如:intage;/* the age of student */floatscore;/* the score of student */floataverage;/* the average of score */longnumber;/* the num
12、ber of student */doubledistance;/* between earth & moon */charUserSelection;/* key user hit */在程序运行时,系统将根据变量的定义为其分配相应大小的内存单元。Q070 为什么在C语言中,整数017和17并不是相同的?(整型)A070 这是因为在C语言中,17是十进制的整数,而017是八进制整数,相当于十进制的15。C语言中对于同一个整型常量,可以有三种不同的形式来表示,即分别用十进制、八进制、十六进制来表示同一个数。为了区分不同进制的整型常量,也为了和其它的标志符区分,C语言中规定,以数字“0”开头的整
13、型常量是八进制的,而以“0x”开头的整型常量的整型是十六进制的。比如十进制整数18,就等价与八进制整数022,也等价与十六进制整数0x12。Q071 在C语言中,整型变量是如何分类的?A071 在C语言中,整型变量分为两大类:有符号整型和无符号整型。而不管是有符号还是无符号整型变量,又都分为基本整型、短整型和长整型三种。分类情况如下表所示:类型关键字占字节数目(Turbo C)有符号signed基本整型signed int2字节短整型signed short int(signed short)长整型signed long int(signed long)4字节无符号unsignedunsign
14、ed intunsigned short int(unsigned short)unsigned long int (unsigned long)其中,有符号整型变量中,关键字signed可以省略。Q072 为什么C语言中,整型变量要分很多种?A072 一方面是因为实际问题当中的数据本来就是具有不同的类型的,更主要的是因为这些数据的变化范围是不同的。不同范围的数据所需要的内存存储单元也是不一样的。因此,必须根据数据的范围来决定给它分配多大的存储空间,而不致发生空间不够或空间浪费的问题。这就好比学校的教学楼里,既有大教室,也有小教室,然后根据来上课的人数分配合适的教室。而不是全部都是大教室,那样
15、就会产生教室不足或教室浪费的问题。C语言提供了多种整型数据类型,不同类型的整型数据占有的字节单元数目是不同的,所以不同类型的整型数据可表示的数的范围也是不同的,这样有助于根据实际数据的最大值来确定其最合适的类型。Q073 那么,到底每种整型变量能保存的数据范围是多少呢?A073 由于每一种整型数据占有的字节单元数目都是有限的,所以每一种整型数据可表示的数的范围也是有限的。ANSI C标准定义的整型类型的表示范围如下表所示:字节数有效表示范围signed int-32768 +327670 +65535signed short intunsigned short intsigned long i
16、nt-2147483648 +2147483647unsigned long int0 +4294967295Q074 有符号和无符号的区别是什么?A074 有符号和无符号的区别关键在于变量所占字节单元中“最高位”的性质。 对于有符号变量:把最高位作为符号位保存数据的符号(0为正,1为负),其余位保存具体数值,因此可以用于正确保存限值范围内的正数或负数。比如有int a; 那么a的有效数值保存范围为 -3276832767。 对于无符号变量:最高位不作为符号位,全部的位都用来保存数据的数值,因此可以用于正确保存限值范围内的正数。比如有unsigned int b; 那么b的有效数值范围为 06
17、5535。Q075 为什么下面的程序中,输出的结果是over=-32768,而不是期望的over=32768?void main() int max, over; max=32767; over=max+1;over=%d, over);A075 因为发生了整型数据的“溢出”问题。前面已经说过,由于每一种整型数据占有的字节单元数目都是有限的,所以每一种整型数据可表示的数的范围也是有限的。程序中,max是int有符号基本整型的变量,所以其有效的数据保存范围就是-32768 +32767。当max等于32767时,实际其所占两个字节中的情况如图所示:max+1后赋值给同样的int有符号基本整型的变
18、量over,则over中实际其所占两个字节中的情况如图所示,很显然已经变成了-32768的补码了。 所以用printf函数按照%d格式显示出来就是-32768。Q076 那怎样才不会出现“整型数据溢出”的问题呢?A076 解决的方法就是,在定义变量时一定要指定合适的类型,保证它所保存的数据在整个程序运行过程中不会超出其能够有效表示的范围。比如,上面的程序中,如果把over定义成unsigned int或long型的变量就可以避免“溢出”的问题。Q077 实型变量是如何分类的?(实型)A077 实型变量的分类如下表所示:单精度双精度floatdouble4 字节8 字节有效数字位数67位1516
19、位数值范围10-3710+3810-30710+308很明显,由于不同的实型数据是用不同数目的有限字节单元保存的,所以它们能表示的数值范围是不同的,能保留的有效数字位数也是不同而且是有限的。Q078 实型数据在内存中是如何存储的?A078实型数据在内存中是以“尾数”和“阶码”的形式存放的。即在一个实型数据(浮点数)所占字节单元中,一部分位用来保存阶码,一部分位用来保存尾数。不同的编译系统位数分配不同。总之,尾数部分位数越多,可以表示的数的有效数字位数就越多,精度就越高;阶码部分位数越多,可以表示的数的范围就越大。Q079 什么是字符型常量?(字符型)A079 的字符常量是用单引号()括起来的一
20、个字符。比如:a、AdD?%$24等等。注意两点:第一,必须是单引号,第二,单引号里只能有一个字符。Q080 为什么字符常量要用单引号括起来?A080 这是为了和程序中其它类型的数据区分开来。比如字符常量,如果不加单引号,只是一个A,那么一定会被编译器认为成一个符号的名字比如变量名。又比如字符常量1,如果不加单引号,只是一个1,那么一定会被编译器认为成是一个整型常量1。因此,必须在所需要的字符周围加上一些称之为“界定符”的字符把它们包围起来,才能和其它数据进行区分。Q081 既然单引号里只能有一个字符,为什么有的程序中会出现n,101这样的字符?A081 这是因为除了前面提到的“单引号括起来的
21、一个字符”形式的字符常量,语言还存在另一种形式的特殊的字符常量,叫“转义字符常量”。它是用单引号括起来的以一个“”字符开头的规定的字符序列。比如问题当中提到的。在转义字符常量中,单引号里面的确是不止一个字符,但实际上整个还是只代表一个字符,也是合法的字符常量。这也就是“转义”之含义。起到转义作用的是单引号当中的 “”,它被用来作为转义字符序列的起始字符。如果单引号中起始字符不是“”,又多于一个字符,那么就不是合法的字符常量了。比如,nn101就不是合法的字符常量。Q082 为什么要用到“转义字符常量”?(字符型)(转义字符常量)A082 因为除了键盘上的所有字符外,程序当中还需要用到一些在键盘
22、上找不到也就无法直接输入的特殊字符。这些字符往往代表了一些独特的特定的功能。因此需要用一种特殊的方法来表示它们,这就产生了“转义字符常量”,也叫“转义字符序列”。Q083 C语言中都支持哪些“转义字符常量”?A083 C语言所支持的转义字符常量如可以分为三大类,如下表所示:Q084 上表中出现的ASCII代码是什么意思?(字符型)(ASCII码)A084ASCII是英文American Standard Code for Information Interchange的缩写,其中文含义是“美国信息交换标准代码”。实际上,ASCII码是一个0255之间的整数。每一个整数对应着一个不同的字符,即每
23、一个字符都有一个不同的整数代码。比如,上表中出现的字符用整数10代表,而单引号本身是用整数39代表的。完整的ASCII码表请参见课本374页。Q085 为什么每一个字符要用一个不同的整数来代表?A085 根本原因在于计算机的基本原理是二进制的。字符型的数据本身是非数值型的,是无法保存在计算机当中的,因为计算机中所有的数据最终都要以二进制数的形式来保存。因此,就要设法将非数值型的数据转换为数值型的数据,从而产生了很多种称之为“字符集”的东西。在各种“字符集”中,把每一个字符用一个唯一的整数来代表。当程序运行时,在出现在该字符的地方实际内存中存储的是该字符对应的整数代码。ASCII就是一种扩充的西
24、文字符集,它把常用的256个字符分别用0255之间的整数来代表。Q086 那么说,C语言中的字符型数据实际上就相当于数值型的数据喽?A086 正是。每个字符型数据无论是常量还是变量在内存中只占一个字节,这个字节中实际保存的就是该字符的ASCII代码。而ASCII码是一个整数,就要按整数的存储方式来保存,因此在C语言中,字符型和整型数据的存储方式是一致的,不同的只是两者占据的字节单元数目。,它的ASCII码是整数65,因此在内存中,字符常量所占的一个字节中实际保存的是整数65,即01000001。反过来看,如果我只知道有一个字节中存放的是01000001,那么我们既可以说它是整数65,也可以说它
25、是字符常量可见,在C语言中,字符型数据和整型数据在一定范围内是通用的,即两者可以相互赋值,相互输出,也可以在一起进行运算。Q087 请举例说明字符型数据和整型数据在一定范围内是通用的?A087 程序如下:#include void main( ) char c1, c2, c3; c1 = ; c2 = b c3 = /* c3保存的是字符空格,ASCII码是32 */ c1 = c1 + 32; /* 字符可以和整数进行算术运算 */ c2 = c2 - c3; /* 字符甚至还可以和字符进行算术运算 */c1 = %c, c1 = %dn, c1, c1); /* 输出结果时,字符既可以显
26、示为字符(%c) */c2 = %c, c2 = %dn, c2, c2); /* 也可以显示整数(%d) */ return;实际上,无论是字符和整数的运算,还是字符和字符的运算,本质上都是整数之间的运算。因此上述程序的运行结果就是:c1=a, c1=97c2=B, c2=66Q088 这么多字符的ASCII码,如何记住它们?A088 根本不需要记住它们,因为你随时都可以查阅ASCII码表得到所需字符的ASCII码。但是,对其中最常用的一些字符,你只需记住它们在ASCII码表中出现的简单规律,就可以记住它们的ASCII码。常用字符及对应ASCII码如下表所示:仔细观察上表,发现规律没有?规律:字符0的ASCII码是48,字符到字符9的ASCII码是连续的;规律:的ASCII码是65,字符Z规律:的ASCII码是97,字符z规律:对应大小写字母的ASCII码之差等于32。Q089 为什么- 0不等于0?(ASCII码)(字符常量)A089 因为是字符型的常量,它实际上相当于其ASCII码整数48,而0就是整数0,所以-0实际上就是48-0,当然不会等于0,应该等
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1