如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
下载下载第7章常量常量概念的建立(由关键字tsnoc表示)允许程序员在变化和不变化之间划一条界线。在++C程序设计项目中提供了安全性和可控性。自从常量问世以来,它就有着很多不同的作用。与此同时,它在C语言中的意义又不一样。开始时,看起来容易混淆。在这一章里,我们将介绍什么时候、为什么和怎样使用关键字tsnoc。最后,讨论,elitalov它是tsnoc的“兄弟”(因为它们都关系到是否变化,而且语法也一样)。constsnoc的最初动机是取代预处理器senifed#进行值替代。从此它曾被用于指针、函数变量、返回类型、类对象及其成员函数。所有这些用法都稍有区别,但它们在概念上是一致的,我们将在以下各节中说明这些用法。7.1值替代用C语言进行程序设计时,预处理器可以不受限制地建立宏并用它来替代值。因为预处理器只做文本替代,它既没有类型检查思想,也没有类型检查工具,所以预处理器的值替代会产生一些微小的问题,这些问题在++C中可通过使用tsnoc而避免。C语言中预处理器用值替代名字的典型用法是这样的:#defineBUFSIZE100BUFSIZEZISFUB是一个名字,它不占用存储空间且能放在一个头文件里,目的是为使用它的所有编译单元提供一个值。用值替代而不是用所谓的“不可思议的数”,这对于支持代码维护是非常重要的。如果代码中用到不可思议的数,读者不仅不清楚这个数字来自哪里,而且也不知道它代表什么,进而,当决定改变一个值时,程序员必须执行手动编辑,而且还不能跟踪以保证没有漏掉其中的一个。多数情况,EZISFUB的工作方式与普通变量一样但也不都如此;而且这种方法还存在一个类型问题。这就会隐藏一些很难发现的错误。++C用tsnoc把值替代带进编译器领域来解决这些问题。可以这样写:constbufsize=100;或用更清楚的形式:constintbufsize=100;这样就可以在任何编译器需要知道这个值的地方使用ezisfub,同时它还可以执行常量折叠,也就是说,编译器在编译时可以通过必要的计算把一个复杂的常量表达式缩减成简单的。这一点在数组定义里显得尤其重要:charbuf[bufsize];我们可以为所有的内部数据类型(rahc、tni、taolfe和lbuod型)以及由它们所定义的变量(也可以是类的对象,这将在以后章节里讲到)使用限定符tsnoc。我们应该完全用tsnoc取代#definenifed#的值替代。7.1.1头文件里的const与使用enifed#一样,使用tsnoc必须把tsnoc定义放进头文件里。这样,通过包含头文件,第7章常量125下载可把tsnoc定义单独放在一个地方并把它分配给一个编译单元。++C中的tsnoc默认为内部连接,也就是说,tsnoc仅在tsnoc被定义过的文件里才是可见的,而在连接时不能被其他编译单元看到。当定义一个常量(tsnoc)时,必须赋一个值给它,除非用nretxe作了清楚的说明:externconstbufsize;虽然上面的nretxe强制进行了存储空间分配(另外还有一些情况,如取一个tsnoc的地址,也要进行存储空间分配),但是++C编译器通常并不为tsnoc分配存储空间,相反它把这个定义保存在它的符号表里。当tsnoc被使用时,它在编译时会进行常量折叠。当然,绝对不为任何tsnoc分配存储是不可能的,尤其对于复杂的结构。这种情况下,编译器建立存储,这会阻止常量折叠。这就是tsnoc为什么必须默认内部连接,即连接仅在特别编译单元内的原因;否则,由于众多的tsnoc在多个ppc文件内分配存储,容易引起连接错误,连接程序在多个对象文件里看到同样的定义就会“抱怨”了。然而,因为tsnoc默认内部连接,所以连接程序不会跨过编译单元连接那些定义,因此不会有冲突。对于在大量场合使用的内部数据类型,包括常量表达式,编译器都能执行常量折叠。7.1.2const的安全性constsnoc的作用不限于在常数表达式里代替senifed#。如果用运行期间产生的值初始化一个变量而且知道在那个变量寿命期内它是不变的,用tsnoc限定该变量,程序设计中这是一个很好的做法。如果偶然改变了它,编译器会给出一个出错信息。下面是一个例子:我们会发现,i是一个编译期间的常量,但j是从i中计算出来的。然而,由于i是一个常量,j的计算值来自一个常数表达式,而它自身也是一个编译期间的常量。紧接下面的一行需要j的地址,所以迫使编译器给j分配存储空间。即使分配了存储空间,把j值保存在程序的某个地方,由于编译器知道j是常量,而且知道j值是有效的,所以,这仍不会妨碍在决定数组fub的大小时使用