第三章 数据类型和表达式 本章详细介绍了C++基本数据类型的定义、C++常量和变量的表示、各种运算符的含义、常用数学函数的原型与功能、各种表达式的构成与求值等内容。目的是使读者对C++基本数据类型和各种运算对象有比较深入的了解,能够在程序设计中得到正确而又灵活地运用。 3.1 数据类型 数据是人们记录事物和活动的符号表示。如记录人的姓名用2~4个汉字表示,记录人的年龄用1~3位十进制数字表示,记录人的高度用带小数点的十进制数表示等。根据数据的性质不同,可以把数据分为不同的类型。在日常使用中,数据主要被分为数值和文字(即非数值)两大类,数值又细分为整数和小数两类。 在C++语言中,数据分类如图3-1所示。 图3-1 C++数据分类 图3-1中每一种无法再分解的数据类型为C++中的一种具体类型。每一种具体类型都对应着唯一的类型关键字、类型长度和值域范围,见表3-1所示,其中有些表项暂时空缺,留待以后介绍。 表3-1 C++数据类型 类型 关键字 长度 值域范围 有符号短整数 short, short int, signed short int 2 -215~215-1内的整数 无符号短整数 unsigned short, unsigned short int 2 0~216-1内的整数 有符号标准整数 int, signed int 4 -231~231-1内的整数 无符号标准整数 unsigned, unsigned int 4 0~232-1内的整数 有符号长整数 long, long int, signed long int 4 -231~231-1内的整数 无符号长整数 unsigned long, unsigned long int 4 0~232-1内的整数 有符号字符 char, signed char 1 -128~+127内的整数 无符号字符 unsigned char 1 0~255内的整数 逻辑 bool 1 0和1两个整数值 枚举 enum <枚举类型名> 4 为int值域内的一个子集 单精度数 float 4 约-3.4×1038~+3.4×1038内的数 双精度数 double 8 约-1.8×10308~1.8×10308内的数 长双精度 long double 8 约-1.8×10308~1.8×10308内的数 指针 <类型关键字> * 4 0~232-1内的整数 引用 <类型关键字> & 4 被引用的变量的值 数组 <类型关键字> [] 结构 struct <结构类型名> 联合 union <联合类型名> 类 class <类类型名> 空值 void 下面对表3-1作几点说明: (1)在每一种类型的关键字一栏中,用逗号分开的各组关键字是等价的,都是表示该类型的关键字。如int和signed int都表示有符号整数类型。 (2)整数类型简称整型。广义的整数类型包括整数类型、字符类型、逻辑类型和枚举类型,一般的整数类型是指短整型(short int)、标准整型(int)和长整型(long int)三种具体类型,标准整数类型最为常用,一般也简称为整型。 (3)对于每一种整数类型和字符类型,又可分为有符号和无符号两种类型。通常使用较多的是有符号类型,所以常把有符号类型简称为所属类型。如把有符号整数类型简称为整型或int型,把有符号字符类型简称为字符型或char型。 (4)类型长度是指存储该类型值域范围内的任一个数据(值)所占有的存储字节数,该字节数由系统规定,并且对任一数据都相同。如短整型长度为2,即存储每个短整数占用2个字节,对应16个二进制位;标准整型长度为4,即存储每个整数占用4个字节,对应32个二进制位;字符型长度为1,即存储每个字符占用1个字节,对应8个二进制位。 (5)类型的值域范围是指该类型所对应的固定大小的存储空间按照相应的存储格式所能表示的值的范围。如对于有符号短整型来说,它对应2个字节的存储空间,存储格式为二进制整数补码格式,用1个二进制为表示符号,用其余的15个二进制位表示数值,它只能够表示(即存储)-215~215-1,即-32 768~+32 767之间的所有整数,共216个整数。若一个整数小于-32 768或大于32 767,则它就不是该类型中的一个值,即它不是一个有符号短整数。又如对于无符号字符类型来说,它对应1个字节的存储空间,存储格式为二进制整数无符号(隐含为正)格式,8位二进制全部用来表示数值,它只能够表示0~28-1,即0~255之间的所有整数。若一个整数小于0或大于255,则它就不是该类型中的一个值,即它不是一个无符号字符数据。 (6)一个数的有效数字是指从该数最左边不为0的数字位起至最右边不为0的数字位止之间的每一个数字位,而这些数字位的个数称为该数的有效数字的位数。如3500、2.705、- 0.278、63.00和0.001 04的有效数字位数分别为2、4、3、2和3。另外,若一个数带有指数部分,则它不影响整个数的有效数字位数。如3.14、3.14×105、314×10- 6等都具有相同的有效数字的位数,即都为3位。 (7)单精度型的值域范围是-3.402 823×1038~3.402 823×1038之间的不超过7位有效数字的所有整数和小数。如-372.65、-0.14×10-6、0.0、+12.7、- 6.45、100.0、8.062×1025等都是单精度范围内的数。2.007 084 63不是单精度范围内的一个数,若舍去它的最后两位有效数字,使之近似为2.007 084,则就成为单精度范围内的一个数。 (8)双精度型的值域范围比单精度型的值域范围更广,精度更高,即能够表示更多的有效数字的位数,它能够表示-1.797 693 134 862 41×10308~1.797 693 134 862 41×10308之间的不超过15位有效数字的所有整数和小数。当一个数的有效数字的位数超过15时,则舍去第15位以后的所有位后,则可近似成为双精度范围内的一个数。在VC++中长双精度型与双精度型定义完全相同。 (9)在VC++ 6.0版本中,标准整型(int)和长整型(long int)具有完全相同的长度和存储格式,所以它们是等同的。但在早期的C++版本中,由于当时的机器字长为16位,所以整型和长整型的长度是不同的,前者为2个字节,后者为4个字节。无论如何,任一种C++语言都遵循short int型的长度小于等于int型长度,同时int型长度又小于等于long ing型长度的规定。 与上述整型情况类似,在VC++ 6.0中,双精度型(double)和长双精度型(long double)也具有完全相同的长度和存储格式,它们是等同的。在其他C++语言中也可能不同,但无论如何,它们都遵循float型的长度小于等于double型长度,同时double型长度又小于等于long double型长度的规定。 使用C++语言中提供的sizeof运算符(该运算符是一个保留字)能够很容易知道任一种数据类型的长度。如sizeof(int)的值就是一个整型的长度,sizeof(long double)的值就是一个长双精度型的长度。使用该运算符的格式有点像函数调用格式,即在后面使用一对圆括号,把类型关键字或某个类型的对象放入其中。 (10)C++中的枚举、数组、结构、联合和类都是需要用户根据相应的语法规则和实际应用进行具体定义的类型,而其他所有类型都是预定义类型,即在C++系统内部已经定义了的类型。对于预定义类型,用户可以在程序中的任何地方直接使用它,对于用户定义类型,只有用户根据需要给出具体定义后,才能够在后面的程序中使用它。 3.2 常量 常量是指在程序执行中不变的量,它分为字面常量和符号常量(又称标识符常量)两种表示方法。如25、-3.26、(a(、(constant(等都是字面常量,即字面本身就是它的值。符号常量是一个标识符,对应着一个存储空间,该空间中保存的数据就是该符号常量的值,这个数据是在定义符号常量时赋予的,是以后不能改变的。如C++保留字中的true和false就是系统预先定义的两个符号常量,它们的值分别为数值1和0,用来分别表示逻辑值“真”和“假”。 关于符号常量的定义和赋初值的方法将在下一节同变量一起讨论,这一节只讨论字面常量的表示方法。 3.2.1 整型常量 整型常量简称整数,它有十进制、八进制和十六进制三种表示。 1.十进制整数 十进制整数由正号(+)或负号(-)开始的、接着为首位非0的若干个十进制数字所组成。若前缀为正号则为正数,若前缀为负号则为负数,若无符号则认为是正数。如38、-25、+120、74 286等都是符合书写规定的十进制整数。 当一个十进制整数大于等于-2 147 483 648即-231,同时小于等于2 147 483 647即231-1时,则被系统看作是int型常量;当在2 147 483 648~4 294 967 295(即232-1)范围之内时,则被看作是unsigned int型常量;当超过上述两个范围时,则无法用C++整数类型表示,只有把它用实数(即带小数点的数)表示才能够被有效地存储和处理。 2.八进制整数 八进制整数由首位数字为0的后接若干个八进制数字(借用十进制数字中的0~7)所组成。八进制整数不带符号位,隐含为正数。如0、012、0377、04056等都是八进制整数,对应的十进制整数依次为0、10、255和2094。 当一个八进制整数大于等于0同时小于等于017777777777时,则称为int型常量,当大于等于020000000000同时小于等于037777777777时,则称为unsigned int型常量,超过上述两个范围的八进制整数则不要使用,因为没有相对应的C++整数类型。 3.十六进制整数 十六进制整数由数字0和字母x(大、小写均可)开始的、后接若干个十六进制数字(0~9、A~F或a~f)所组成。同八进制整数一样,十六进制整数也均为正数。如0x0、0x25、0x1ff、0x30CA等都是十六进制整数,对应的十进制整数依次为0、37、511和12 490。 当一个十六进制整数大于等于0同时小于等于0x7FFFFFFF时,则称为int型常量,当大于等于0x80000000同时小于等于0xFFFFFFFF时,则称为unsigned int型常量,超过上述两个范围的十六进制整数没有相对应的C++整数类型,所以不能使用它们。 4.在整数末尾使用u和l字母 对于任一种进制的整数,若后缀有字母u(大、小写等效),则硬性规定它为一个无符号整型(unsigned int)数,若后缀有字母l(大、小写等效),则硬性规定它为一个长整型(long int)数。在一个整数的末尾,可以同时使用u和l,并且对排列无要求。如25U、 0327UL、0x3ffbL、648LU等都是整数,其类型依次为unsigned int、unsigned long int、long int和unsigned long int。 3.2.2 字符常量 字符常量简称字符,它以单引号作为起止标记,中间为一个或若干个字符。如(a(、(%(、(\n(、(\012(、(\125(、(\x4F(等都是合乎规定的字符常量。每个字符常量只表示一个字符,当字符常量的一对单引号内多于一个字符时,则将按规定解释为一个字符。如(a(表示字符a,(\125(解释为字符U(稍后便知是如何解释的)。 因为字符型的长度为1,值域范围是-128~127或0~255,而在计算机系统使用的ASCII字符,其ASCII码值为0~127,正好在C++字符型值域内。所以,每个ASCII字符均是一个字符型数据,即字符型中的一个值。 对于ASCII字符集中的每个可显示字符(个别字符除外),对应的C++字符常量就是它本身,对应的值就是该字符的ASCII码,表示时用单引号括起来;对于像回车、换行那样的具有控制功能的字符,以及对于像单引号、双引号那样的作为特殊标记使用的字符,就无法采用上述的表示方法。为此引入了“转义”字符的概念,其含义是:以反斜线作引导的下一个字符失去了原来的含义,而转义为具有某种控制功能的字符。如(\n(中的字符n通过前面使用的反斜线转义后就成为一个换行符,其ASCII码为10。为了表示用作特殊标记使用的可显示字符,也需要用反斜线字符引导。如(\(表示单引号字符,若直接使用( (表示单引号是不行的,因为此时的单引号具有二义性。 另外,还允许用反斜线引导一个具有1~3位的八进制整数或一个以字母x作为开始标记的具有1~2位的十六进制整数,对应的字符就是以这个整数作为ASCII码的字符。如(\0(、(\12(、(\73(、(\146(、(\x5A(等对应的字符依次为空字符(其ASCII码为0,它不同于空格字符,空格字符的ASCII码为32)、换行符、(;(、(f (和(z(等。 由反斜线字符开始的符合上述使用规定的字符序列称为转义序列,C++语言中的所有转义序列如表3-2所示。 表3-2 C++转义序列字符列表 转义序列 对应值 对应功能或字符 转义序列 对应值 对应功能或字符 \a 7 响铃 \\ 92 反斜线 \b 8 退格 \( 39 单引号 \f 12 换页 \( 34 双引号 \n 10 换行 \? 63 问号 \r 13 回车 \ccc ccc的十进制值 该值对应的字符 \t 9 水平制表 \xhh hh的十进制值 该值对应的字符 \v 11 垂直制表 转义序列不但可以作为字符常量,也可以同其他字符一样使用在字符串中。如(abc\n(字符串中含有四个字符,最后一个为换行符,(\tx=(中的首字符为水平制表符,当输出它时将使光标后移8个字符位置。 对于一个字符,当用于输出显示时,将显示出字符本身或体现出相应的控制功能,当出现在计算表达式中时,将使用它的ASCII码。如: (1)char ch=(E(; (2)int x=ch+2; (3)if(ch>(C() cout<(<<(C(<(C(比较,实际上是取出各自的值(即对应的ASCII码)比较,因ch的值69大于(C(的值67成立,所以执行其后的输出语句,将向屏幕输出E>C。第(4)条语句输出一个字符串,即原样输出apple,接着使光标移到下一行开始位置。 3.2.3 逻辑常量 逻辑常量是逻辑类型中的值,VC++用保留字bool表示逻辑类型,该类型只含有两个值,即整数0和1,用0表示逻辑假,用1表示逻辑真。在VC++中还定义了这两个逻 辑值所对应的符号常量false和true,false的值为0,表示逻辑假,true的值为1,表示逻辑真。 由于逻辑值是整数0和1,所以它也能够像其他整数一样出现在表达式里,参与各种整数运算。如true+2的值等于3。 3.2.4 枚举常量 枚举常量是枚举类型中的值,即枚举值。枚举类型是一种用户定义的类型,只有用户在程序中定义它后才能被使用。用户通常利用枚举类型定义程序中需要使用的一组相关的符号常量。枚举类型的定义格式为: enum <枚举类型名> {<枚举表>}; 这是一条枚举类型定义语句,该语句以enum保留字开始,接着为枚举类型名,它是用户命名的一个标识符,以后就直接使用它或连同保留字enum一起使用表示该类型,枚举类型名后为该类型的定义体,它是由一对花括号和其中的枚举表所组成,枚举表为一组用逗号分开的符号常量,每个符号常量为由用户命名的一个标识符,每个符号常量又称为枚举常量或枚举值。如: (1)enum color{red, yellow, blue}; (2)enum day{Sun, Mon, Tues, Wed, Thur, Fri, Sat}; 第(1)条语句定义了一个枚举类型color,也可以写为enum color,用来表示自定义的颜色类型,它包含3个枚举值red、yellow和blue,分别代表红色、黄色和蓝色。 第(2)条语句定义了一个枚举类型day,也可以写为enum day,用来表示自定义的星期类型,它包含7个枚举值,分别对应表示星期日、星期一至星期六。 一种枚举类型被定义后,可以像整型等预定义类型一样使用在允许出现数据类型的任何地方,如可以利用它定义变量。 (1)enum color c1,c2,c3; (2)enum day today, workday; (3)c1=red; (4)workday=Wed; 第(1)条语句开始的保留字enum和类型标识符colou表示上述定义的枚举类型color,其中enum可以省略不写,后面的三个标识符c1、c2和c3分别表示该类型的3个变量,每个变量可以用来存储该枚举表中列出的任一个值。 第(2)条语句开始的两个成分表示上述定义的枚举类型day,同样enum可以省略不写,后面的两个标识符today和workday表示该类型的两个变量,每个变量可以用来存储该枚举表中列出的7个值中的任一个值。 第(3)条语句把枚举值red赋给变量c1。第(4)条语句把枚举值Wed赋给变量 workday。 在一个枚举类型的枚举表中列出的每一个枚举常量都对应着一个整数值,该整数值可以由系统自动确认,也可以由用户指定。若用户在枚举表中一个枚举常量后加上赋值号和一个整型常量,则就表示枚举常量被赋予了这个整型常量的值。如: enum day{Sun=7, Mon=1, Tues, Wed, Thur, Fri, Sat}; 用户指定了Sun的值为7,Mon的值为1。 若用户没有给一个枚举常量赋初值,则系统给它赋予的值是它前一项枚举常量的值加1,若它本身就是首项,则被自动赋予整数0。如对于上述定义的color类型,red、yellow和blue的值分别为0、1和2;对于刚被修改定义的day类型,各枚举常量的值依次为7、1、2、3、4、5和6。 由于各枚举常量的值是一个整数,所以可把它同一般整数一样看待,参与整数的各种运算。又由于它本身是一个符号常量,所以当作为输出数据项时,输出的是它的整数值,而不是它的标识符,这一点同输出其他类型的符号常量是一致的。 3.2.5 实型常量 实型常量简称实数,它有十进制的定点和浮点两种表示方法,不存在其他进制的表示。 1.定点表示 定点表示的实数简称定点数,它是由一个符号(正号可以省略)后接若干个十进制数字和一个小数点所组成,这个小数点可以处在任何一个数字位之前或之后。如.12、1.2、12.、0.12、-12.40、+3.14、-.02037、-36.0等都是符合书写规定的定点数。 2.浮点表示 浮点表示的实数简称浮点数,它是由一个十进制整数或定点数后接一个字母e(大、小写均可)和一个1~3位的十进制整数所组成,字母e之前的部分称为该浮点数的尾数,之后的部分成为该浮点数的指数,该浮点数的值就是它的尾数乘以10的指数幂。如3.236E5、+3.25e-8、2E4、0.376E-15、1e-6、- 6.04E+12、.43E0、96.e24等都是合乎规定的浮点数,它们对应的数值分别为3.236×105、3.25×10-8、20000、0.376×10-15、10-6、-6.04×1012、0.43、96×1024等。 对于一个浮点数,若将它尾数中的小数点调整到最左边第一个非零数字的后面,则称之为规格化(或标准化)的浮点数。如21.6E8和-0.074E5都是非规格化的,若将它们分别调整为2.16E9和-7.4E3则都变为了规格化的浮点数。 3.实数类型 对于一个定点数或浮点数,被C++自动处理为一个双精度数,存储它占用8个字节的存储空间。若在一个定点数或浮点数之后加上字母f(大、小写均可),则自动按一个单精度数看待,存储它占用4个字节的存储空间。如3.24和3.24f,虽然数值相同,但分别代表一个双精度数和一个单精度数,同样,-2.78E5为一个双精度数,而-2.78E5F为一个单精度数。 3.2.6 地址常量 指针类型的值域是0~232-1之间的所有整数,每一个整数代表内存空间中一个对应单元(若存在的话)的存储地址,每一个整数地址都不允许用户直接使用来访问内存,以防止用户对内存系统数据的有意或无意的破坏。内存地址的分配和管理是由计算机操作系统直接控制和进行的,用户仅能够直接使用整数0作为地址常量,它是C++中唯一允许使用的地址常量,并称为空地址常量,它对应的符号常量为NULL。此常量并不是指内存中编号为0的存储字节地址,而转义为不代表任何地址,或称为空地址。符号常量NULL在iostream.h等头文件中所包含的ios.h头文件里有定义,其值为0。 3.3 变量 变量是用标识符表示的、其值可以被改变的量。每一个变量都属于一种数据类型,用来表示(即存储)该类型中的一个值。在程序中只有存在了一种数据类型后,才能够利用它定义出该类型的变量。根据这一原则,我们可以随时利用C++语言中的每一种预定义类型和用户已经定义的每一种类型定义所使用的变量。一个变量只有被定义后才能被访问,即才能进行存储和读取其值的操作。 1.变量定义语句 变量定义是通过变量定义语句实现的,该语句的一般格式为: <类型关键字> <变量名>[=<初值表达式>],…; <类型关键字>为已存在的一种数据类型,如short、int、long、char、bool、float、double等都是类型关键字,分别代表系统预定义的短整型、整型、长整型、字符型、逻辑型(又称布尔型)、单精度型和双精度型。对于用户自定义的类型,可从类型关键字中省略其保留字。如假定struct worker是用户自定义的一种结构类型,则前面的保留字struct可以省略。 <变量名>是用户定义的一个标识符,用来表示一个变量,该变量可以通过后面的可选项,即赋值号和<初值表达式>赋予一个值,称为给变量赋初值。 该语句格式后面使用的省略号表示在一条语句中可以定义多个变量,但各变量定义之间必须用逗号分开。 2.语句格式举例 (1)int a,b; (2)char ch1='a', ch2='A'; (3)int x=a+2*b; (4)double d1, d2=0.0, d3=3.14159; 第(1)条语句定义了两个整型变量a和b;第(2)条语句定义了两个字符变量ch1和ch2,并被分别赋初值为字符a和A;第(3)条语句定义了一个整型变量x,并赋予表达式a+2*b的值作为初值,若a和b的值分别为1和2,则x的初值为5;第(4)条语句定义了三个双精度变量,分别为d1、d2和d3,其中d2被赋予初值0.0,d3被赋予初值3.14159。 3.语句执行过程 程序在编译阶段处理每条变量定义语句时,是把被定义的每个变量的类型、变量名等信息登记下来,以便在执行阶段为其分配相应的存储空间。程序在执行阶段处理每条变量定义语句时,若变量定义中带有初值表达式,则进行初值表达式的计算,并把计算结果赋给变量;若不带有初值表达式,且所属的语句处于所有函数之外,则将被自动赋予初值0;若既不带有初值表达式,又处于一个函数体之内,则不会被赋予任何值,此时的变量值是不确定的,实际上是存储单元中的原有值(现在被称为垃圾)。 4.语句应用举例 假定要计算一个圆的周长和面积,则圆的半径、周长和面积都需要设定为变量,假定分别用radius、girth和area标识符表示,它们的类型均应为实数型,即单精度或双精度型,通常使用双精度型。根据圆的半径计算周长和面积的公式为: girth=2((radius area=((radius(radius 下面给出用C++语言编写的计算程序: #include const double PI=3.14159; //把圆周率定义为符号常量 void main() { double radius, girth, area; //定义变量 cin>>radius; //从键盘输入一个圆的半径 girth=2*PI*radius; //计算周长 area=PI*radius*radius; //计算面积 cout<<"radius:"< <符号常量名>=<初值表达式>,…; 该语句以保留字const开始并标识,后跟符号常量的类型关键字,接下去为符号常量名,它是一个用户定义的标识符,符号常量名之后为一个赋值号和一个初值表达式,在此为必选项,而在一般的变量定义语句中为任选项,这表明在定义符号常量时必须同时对其赋初值。该语句同样也可以定义多个符号常量。 一个符号常量被定义后,它的值就是定义时所赋予的初值,以后将一直保持不变,用户只能够读取它的值,而不能够再向它赋值。 另外,在符号常量的定义语句中,若<类型关键字>为int,则可以被省略。但为了提高程序的可读性,最好不要采用其省略类型。 下面给出3条符号常量定义语句的例子。 (1)const int A1=5, A2=A1*4; 60 C++语言基础教程(第二版) 59 第三章 数据类型和表达式