购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 C++语句

C++程序是一组函数,而每个函数又是一组语句。C++有好几种语句,下面介绍其中的一些。程序清单2.2提供了两种新的语句。声明语句创建变量,赋值语句给该变量提供一个值。另外,该程序还演示了cout的新功能。

程序清单2.2 carrot.cpp

空行将声明语句与程序的其他部分分开。这是C常用的方法,但在C++中不那么常见。下面是该程序的输出:

下面探讨这个程序。

计算机是一种精确的、有条理的机器。要将信息项存储在计算机中,必须指出信息的存储位置和所需的内存空间。在C++中,完成这种任务的一种相对简便的方法,是使用声明语句来指出存储类型并提供位置标签。例如,程序清单2.2中包含这样一条声明语句(注意其中的分号):

这条语句提供了两项信息:需要的内存以及该内存单元的名称。具体地说,这条语句指出程序需要足够的存储空间来存储一个整数,在C++中用int表示整数。编译器负责分配和标记内存的细节。C++可以处理多种类型的数据,而int是最基本的数据类型。它表示整数—没有小数部分的数字。C++的int类型可以为正,也可以为负,但是大小范围取决于实现。第3章将详细介绍int和其他基本类型。

完成的第二项任务是给存储单元指定名称。在这里,该声明语句指出,此后程序将使用名称carrots来标识存储在该内存单元中的值。carrots被称为变量,因为它的值可以修改。在C++中,所有变量都必须声明。如果省略了carrots.cpp中的声明,则当程序试图使用carrots时,编译器将指出错误。事实上,程序员尝试省略声明,可能只是为了看看编译器的反应。这样,以后看到这样的反应时,便知道应检查是否省略了声明。


为什么变量必须声明?

有些语言(最典型的是BASIC)在使用新名称时创建新的变量,而不用显式地进行声明。这看上去对用户比较友好,事实上从短期上说确实如此。问题是,如果错误地拼写了变量名,将在不知情的情况下创建一个新的变量。在BASIC中,ss程序员可能编写如下语句:

由于CastleDank是拼写错误(将r拼成了n),因此所作的修改实际上并没有修改CastleDark。这种错误很难发现,因为它没有违反BASIC中的任何规则。然而,在C++中,将声明CastleDark,但不会声明被错误拼写的CastleDank,因此对应的C++代码将违反“使用变量前必须声明它”的规则,因此编译器将捕获这种错误,发现潜在的问题。


因此,声明通常指出了要存储的数据类型和程序对存储在这里的数据使用的名称。在这个例子中,程序将创建一个名为carrots的变量,它可以存储整数(参见图2.4)。

图2.4 变量声明

程序中的声明语句叫作定义声明(defining declaration)语句,简称为定义(definition)。这意味着它将导致编译器为变量分配内存空间。在较为复杂的情况下,还可能有引用声明(reference declaration)。这些声明命令计算机使用在其他地方定义的变量。通常,声明不一定是定义,但在这个例子中,声明是定义。

如果您熟悉C语言或Pascal,就一定熟悉变量声明。不过C++中的变量声明也可能让人小吃一惊。在C和Pascal中,所有的变量声明通常都位于函数或过程的开始位置,但C++没有这种限制。实际上,C++通常的做法是,在首次使用变量前声明它。这样,就不必在程序中到处查找,以了解变量的类型。本章后面将有一个这样的例子。这种风格也有缺点,它没有把所有的变量名放在一起,因此无法对函数使用了哪些变量一目了然(C99标准使C声明规则与C++非常相似)。


提示:

对于声明变量,C++的做法是尽可能在首次使用变量前声明它。


赋值语句将值赋给存储单元。例如,下面的语句将整数25赋给变量carrots表示的内存单元:

符号=叫作赋值运算符。C++(和C)有一项不寻常的特性—可以连续使用赋值运算符。例如,下面的代码是合法的:

赋值将从右向左进行。首先,88被赋给steinway;然后,steinway的值(现在是88)被赋给baldwin;然后baldwin的值88被赋给yamaha(C++遵循C的爱好,允许外观奇怪的代码)。

程序清单2.2中的第二条赋值语句表明,可以对变量的值进行修改:

赋值运算符右边的表达式carrots – 1是一个算术表达式。计算机将变量carrots的值25减去1,得到24。然后,赋值运算符将这个新值存储到变量carrots对应的内存单元中。

到目前为止,本章的示例都使用cout来打印字符串,程序清单2.2使用cout来打印变量,该变量的值是一个整数:

程序没有打印“carrots”,而是打印存储在carrots中的整数值,即25。实际上,这将两个操作合而为一了。首先,cout将carrots替换为其当前值25;然后,把值转换为合适的输出字符。

如上所示,cout可用于数字和字符串。这似乎没有什么不同寻常的地方,但别忘了,整数25与字符串“25”有天壤之别。该字符串存储的是书写该数字时使用的字符,即字符2和5。程序在内部存储的是字符2和字符5的编码。要打印字符串,cout只需打印字符串中各个字符即可。但整数25被存储为数值,计算机不是单独存储每个数字,而是将25存储为二进制数(附录A讨论了这种表示法)。这里的要点是,在打印之前,cout必须将整数形式的数字转换为字符串形式。另外,cout很聪明,知道carrots是一个需要转换的整数。

与老式C语言的区别在于cout的聪明程度。在C语言中,要打印字符串“25”和整数25,可以使用C语言的多功能输出函数printf( ):

撇开printf( )的复杂性不说,必须用特殊代码(%s和%d)来指出是要打印字符串还是整数。如果让printf( )打印字符串,但又错误地提供了一个整数,由于printf( )不够精密,因此根本发现不了错误。它将继续处理,显示一堆乱码。

cout的智能行为源自C++的面向对象特性。实际上,C++插入运算符(<<)将根据其后的数据类型相应地调整其行为,这是一个运算符重载的例子。在后面的章节中学习函数重载和运算符重载时,将知道如何实现这种智能设计。


cout和printf( )

如果已经习惯了C语言和printf( ),可能觉得cout看起来很奇怪。程序员甚至可能固执地坚持使用printf( )。但与使用所有转换说明的printf( )相比,cout的外观一点也不奇怪。更重要的是,cout还有明显的优点。它能够识别类型的功能表明,其设计更灵活、更好用。另外,它是可扩展的(extensible)。也就是说,可以重新定义<<运算符,使cout能够识别和显示所开发的新数据类型。如果喜欢printf( )提供的细致的控制功能,可以使用更高级的cout来获得相同的效果(参见第17章)。 dzsxSNSWY+3kpwGv1ctdJo+Neq4/C7nN5eI0G+HAcqeznQ1vC8nj0Wvn+5rDqQO4


点击中间区域
呼出菜单
上一章
目录
下一章
×

打开