面向对象编程的本质时设计并扩展自己的数据类型。
内置的C++类型分两组:基本类型和复合类型。
基本类型:整数和浮点数。
复合类型:数组、字符串、指针、结构。
3.1 简单变量
为了把信息储存在计算中,程序必须记录3个基本属性:
储存何种类型的信息;
要储存什么值;
信息将要存储在什么地方;
使用&运算符来检索变量的内存地址。
3.1.1 变量名
C++提倡使用有一定含义的变量名。
cost_of_trip;(匈牙利命名)
costOfTrip;(驼峰命名)
C++命名规则:
在名称中只能使用字母字符、数字和下划线;
名称的第一个字符不能是数字;
区分大小写字符;
不能将C++关键字用作名称;
以两个下划线大头或以下划线和大写字母开始的名称被保留给实现(编译器及其他使用的资源)。以一个下划线开头的名称被保留给实现,用作全局标识符。
3.1.2 整型
使用的内存量越大,可以表示的整数值范围范围就越大。
3.1.3 整型short,int,long long
C++确保了整型的最小长度:
short至少16位;
int至少与short一样长;
long至少32位,且至少和int一样长;
long long 至少64位,且至少和long一样长;
字节Byte通常指的是8位内存单元。
sizeof运算符返回类型或变量的长度,单位为字节。
头文件climits包含了关于整型限制的信息。
#define 编译指令的工作方式与文本编辑器或字处理器中的全局搜索并完成替换命令相似。修改后的程序将在完成这些替换后被编译。
初始化将赋值与声明合并在一起。也可以使用字面值常量来初始化,可以将变量初始化为另一个变量,条件是后者以及定义过。也可以用表达式来初始化变量,条件是当程序执行到该声明,表达式中所有的值都是已知的。
如果不对函数定义的变量初始化,该变量的值将是不确定的。这意味着该变量的值将是它被创建之前的,相应内存单元保存的值。
在声明变量时并对它进行初始化,可壁面以后忘记给它赋值的情况发生。
C++11 大括号初始化。使用大括号初始化器,初始化常规变量的方式与初始化类变量的方式更像。 C++11 使得可将大括号初始化器用于任何类型(可以使用等号,也可以不使用),这是一种通用的初始化语法。
3.1.4 无符号类型
当使用无符号整型变量是,其优点是可以增大变量能够储存的最大值。当然,仅当数值不会为负才应使用无符号整型。unsigned
这些整型变量的行为就像里程表。如果超越了限制,其值将从范围另一端取值。
C++并不保证符号整型超越限制(上溢和下溢)时不出错。
3.1.5 选择整数类型
int被设置成对目标计算机而言最”自然“的长度。自然长度是指计算机处理起来效率最高的长度。
3.1.6 整数字面值
如果第一位是1~9,则基数是10(进制);
如果第一位是0,第二位是1~7,则基数是8(进制);
如果前两位是0x或0X,则基数是16(进制),对于16进制,字符a~f和A~F表示了10~15.
dec, hex, 和oct,分别用于指示cout以十进制、十六进制和八进制格式显示数字。
3.1.7 C++如何确定常量类型
除非有理由存储为其他类型,否则C++将整型常量存储为int类型。
整型变量后缀,l/L表示long, u表示unsigned, ll/LL表示long long。
3.1.8 char类型
char类型是专为存储字符(如字母和数字)而设计的。
char类型是另一种整型。它足够长,能够表示目标计算机系统中的所有基本符号--所有的字母、数字、标点符号。实际上,很多系统支持的字符都不超过128个,因此用一个字节就可以表示所有的符号。
C++对字符用单引号,对字符串用双引号。
C++将字符表示为整数这一事实,使得操纵字符值很容易。
句点被称为成员运算符。
C++将字符常量存储为char类型,而不是int类型。
对于一些特殊的ASCII符号,'', ', \等, 可以用转义序列表示。
显示数字时, 使用endl比输入”\n“更容易点,但显示字符串时,则\n方便点。
程序需要处理的字符集可能无法用一个8位的字节表示。
一种实现可以同时支持一个小型基本字符集和一个较大的扩展字符集。8位char可以表示基本字符集。另一种类型wchar_t(宽字符类型)可以表示扩展字符集。
cin和cout将输入输作char流,因此不适用处理wchar_t类型。其wcin和wcout版本可以处理宽字符类型。
3.1.9 bool类型
布尔变量的值可以时true和false。
C++将非零值解释为true, 将零解释为false。
字面值true和false都可以通过提升转换位int类型,true为1, false为0。
任何数字值或指针值都可以被隐士转换为bool值。任何非零值都被转换为true,而零被转换为false。
3.2 const 限定符
除#define预处理器方法外, C++处理符号常量的更好的方法,即使用const限定符。关键字const叫做限定符,因为它限制了声明的含义。
一种常见的做法是将名称的首字母大写,以提醒您其是常量。另一种是将整个名称大写。
3.3 浮点数
浮点数能够表示带小数部分的数字。计算机将浮点数的值分两部分存储。一部分表示值,另一部分对值进行放大或者缩小。缩放因子的作用是移动小数点的位置,术语浮点因此而得名。
3.3.1 书写浮点数
第二种表示浮点值的方法叫做E表示法。3.45e4。指数为负数意味着除以10的乘方,而不是乘以10的乘方。
3.3.2 浮点类型
C++也有3中浮点类型:float, double, long double. 这些类型是按它们可以表示的有效数位和允许的指数最小范围来描述的。有效位(significant figure)是数字中有意义的位。 有效位不依赖于小数点的位置。有效位不依赖于小数点位置。如14000, 2个有效位。14547, 5个有效位。14.567,5个有效位。
C++对于有效位的要求是,float至少32位,double至少48位,long double 不能少于double。通常float, 32位;double, 64位;long double 80, 96, 128。
ostream方法setf(),这种调用迫使输出使用定点输出,防止程序将较大值于较小值切换为E表示法,并使程序显示到小数点后6位。
cout所属的ostream类有一个成员函数,能够精确地控制输出地格式--字段宽度、小数位数、采用小数格式还是E格式。
3.3.3 浮点常量
如果希望常量使float类型,请使用f或者F后缀。对于long double类型,可以使用l或者L后缀;
3.3.4 浮点数的优缺点
与整数相比,浮点数有两大优点。首先,它们能表示整数之间的数。其次,由于有压缩因子,它们可以表示的范围大得多。最后浮点数运算通常比整数运算慢,且精度将降低。
整型和浮点型统称为算术(arithmetic)类型
3.4 C++运算符
C++提供5种基本算数运算符:加法+、减法-、乘法*、除法/和求模%。此5种都是2元操作符。
%求模运算符规定两个操作数必须都是整数,将该运算符用于浮点数将导致编译错误。如果其中有一个负数,则结果的符号满足以下规则:(a / b) * b + a % b = a。
对于float,C++只保证6位有效位。如果需要更高精度,请使用doube或long double。
3.4.1 运算符的优先级和结合性
算数运算符遵从通常的代数优先级,先乘除后加减。
当然,也可以使用括号来执行自己定义的优先级。
当两个运算符的优先级相同时,C++将看操作数的结合性(associativity)是从左到右,还是从右到左。
int a = 4 * 2 / 3;
仅当两个运算符被用于同一个操作数时,优先级和结合性规则才有效。
int dues = 20 * 5 + 24 * 6;
3.4.2 除法分支
除法运算符的行为取决于操作数的类型。如果两个操作数都是整数,则C++将执行整数除法。若至少一个操作数是浮点数,则小数部分将保留。
实际上,对不同类型进行运算时,C++将它们全部转换为同一类型。
C++根据上下文(操作数的类型)来确定运算符的含义。使用相同的符号进行多种操作叫做运算符重载(operator overloading)。
3.4.3 求模运算符
求模运算符返回整数除法的余数。它与整数除法相结合,尤其适用于解决将一个量分成不同整数单元的问题。
3.4.4 类型转换
尤其对不同的类型进行运算的时候,为处理潜在的混乱,C++自动执行很多类型转换:
将一种算术类型的值赋给另一种算术类型的变量时,C++将对值进行转换;
表达式种包含不同的类型时,C++将对值进行转换;
将参数传递给函数时,C++将对值进行转换;
C++允许将一种类型的值赋给另一种类型的变量。这样做时,值将被转换为接收变量的类型。
将一个很大的long值赋给float变量将降低精度。因为float只占6位有效数字。
潜在的数值转换问题
转换 | 潜在的问题 |
double -- float | 进度降低,值可以超过目标类型的取值范围,结果不确定。 |
float -- int | 小数部分丢失,值可以超过目标类型的取值范围,结果不确定。 |
long int -- short --int | 原有值可能超过目标类型取值范围,通常只复制右边字节。 |
将0赋给bool变量,将被转化伪false;而非零值将被转化为true;
C++ 11 将使用大括号的初始化称为列表初始化(list initialization),该初始化方式常用于给复杂的数据类型提供值列表。
列表初始化不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。
当同一个表达式中包含两种不同的算术类型时,将出现情况? C++将执行两种自动转换。首先,一些类型会出现时就自动转换。其次,有些类型在于其他类型同时出现在表达式中时被转换。
先看看自动转换。在计算表达式时,C++将bool, char, unsigned char, signed char和short类型值转换为int。此类转换为整型提升(integral promotion)。确保了提升过程不会损失数据。
将不同类型进行算数运算时,较小的类型将被转换为较大类型。
大致转换路线是:
如果有long double,另一个转换为long double;
否则,有double,另一个转换为double;
否则,有float,另一个转换为float;
否则,说明操作数都是整型,实先整型提升;
否则,如果两个操作数都是有符号或无符号,且其中一个操作数级别比另一个低,则转换为级别高的类型;
如果一个有符号,一个无符号,且无符号操作数级别比有符号级别高,则有符号转换为无符号操作数类型;
否则,如果有符号类型可以表示无符号类型的所有可能取值,则将无符号转换为有符号;
否则,将两个操作数都转化为有符号类型的无符号版本;
传递参数时的类型转换通常由C++函数原型控制。
C++还引入了4个强制类型转换运算符,static_cast<typeName>(value)。使用强制类型转换的最常见的原因--使一种格式的数据能够满足不同的期望。
3.4.5 auto声明
C++11 新增了auto声明,如果使用了关键字auto,而不指定变量的类型,编译器将把类型设置称于初始值相同。
处理复杂类型,如STL中的类型,自动类型推导auto的优势才体现出来。
3.5 总结
C++ 基本类型分两类:一组由存储为整数的值组成,另一组由存储为浮点格式的值组成。
整型之间通过存储值使使用的内存量及有无符号来区分。整型从小到最大以此是:bool,char,signed char,unsigned char,short,unsigned short,int, unsigned int, long, unsigned long,long long 和unsigned long long。
字符通过其数值编码来表示。I/O系统据欸的那个了编码是被解释为字符还是数字。
浮点类型可以表示小数值以及比整数能够表示的值大得多的值。3中浮点类型分别是float,double,和long double。float 32位, double 64位, long double 80~128位。
C++使用运算符来提供对数字类型的算术运算:加减乘除求模。
当两个运算符对同一个操作数进行操作时,C++的优先级和结合性规则可以确定先执行那种操作。
对于变量赋值,在运算中使用不同的类型、使用强制类型转换,C++将把值从一种类型转换为另一种类型。