![C++ 从入门到项目实践(超值版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/805/26846805/b_26846805.jpg)
4.2 数据基本类型
数据类型是不同形式的信息在内存中分配方式的基本约定,是构建程序的基础。在C++语言中定义了很多的数据类型,本节将介绍常用的预定义数据类型有字符类型、整数类型、浮点数类型、布尔类型、无类型和宽字符类型等,以及这些类型的基本用法,C++的基本类型如图4-3所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P55_8625.jpg?sign=1739410739-qPjTTjxEPBl1LWishoOLXNQstnwQBsTK-0-9c5c34cd82f2d3dcebd4c3c35ba2fab6)
图4-3 数据基本类型
4.2.1 整数类型(int)
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P55_8636.jpg?sign=1739410739-yk3JhEr8uEuRDAGRHzjOtCjYMH4ZEjfB-0-31ec73ad98e1c15eaf23c4a7d87aa3a0)
在C++中,整型数据即为整数,是不包含小数部分的数值型数据。整型数据分为长整型(long int)、一般整型(int)和短整型(short int)。在int前面加long和short分别表示长整型和短整型。
整型数据的存储方式为按二进制数形式存储,例如十进制整数89的二进制形式为1011001,其在内存中的存储形式如图4-4所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P55_8630.jpg?sign=1739410739-M8tpEzmPPvHpYH9iKoNwkCHcTccVt7L1-0-4eb5e3d53bef75801f9b2392e60ac477)
图4-4 整型数据的储存形式
在整型符号int和字符型符号char的前面,可以加修饰符signed(表示“有符号”)或unsigned(表示“无符号”)。如果指定为signed,则数值以补码形式存放,存储单元中的最高位(bit)用来表示数值的符号。如果指定为unsigned,则数值没有符号,全部二进制位都用来表示数值本身,如图4-5所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P55_8633.jpg?sign=1739410739-kjB09irJdjy2uH8x6Rv4z7CSuJ9U4EL8-0-d2761ef3edca03cedd915bc8dba90947)
图4-5 有符号与无符号数据的储存形式
有符号时,能存储的最大值为215-1,即32 767,最小值为-32 768。无符号时,能存储的最大值为216-1,即65535,最小值为0。有些数据是没有负值的,可以使用unsigned,它存储正数的范围比用signed时要大一倍。整型数据的取值范围见表4-4。
表4-4 整型数据的类型说明以及取值范围
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-T56_71531.jpg?sign=1739410739-8yQOfaTFYy5ds3WLsmJYhysvaQGTmAdZ-0-3408ab1aa6906c35e88438ff45f5c5c5)
注意:表中类型标识符一栏中,方括号[ ]包含的部分可以省写,如short和short int等效,unsigned int和unsigned等效。
4.2.2 字符类型(char)
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P56_8864.jpg?sign=1739410739-h32U9o6zHjclSaIF8r61XW8D1Phu8i9w-0-dbf5decde74b83b273c52070af2990b6)
字符类型数据是用一对单引号括起来的一个字符,单引号只是字符与其他部分的分割符,不是字符的一部分。
例如:
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P56_71527.jpg?sign=1739410739-t0hufVpwA23TUiYLBEWgU3Qysh57xsGE-0-780586aedf4ffa1b6ee560ff4d570275)
并且,不能用双引号代替单引号。在单引号中的字符不能是单引号或反斜杠。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P56_71526.jpg?sign=1739410739-sUKwEHgMEAGj4qdPInfnN6jJt88BEIzZ-0-a24a08fa1138f272f48d2a0ad85036c1)
另一种表示字符常量的方法是使用转义字符。C++规定,采用反斜杠后跟一个字母来代表一个控制字符,具有新的含义。
C++中常用的转义字符见表4-5。
表4-5 C++中常见的转义字符
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-T56_8868.jpg?sign=1739410739-V9EXFUWPGrofgDMWMMtY4J6i3iO4iguq-0-e261d72d2c92695d339386f93438833d)
【例4-1】编写程序,输出字符型数据。
(1)在Visual Studio 2017中,新建名称为“4-1.cpp”的Project1文件。
(2)在代码编辑区域输入以下代码。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P57_9021.jpg?sign=1739410739-p7fzo2u08GTTDiMa4qldbnJuxy9oTVUL-0-aa5d9217cc38c1a3484e53f03059cb8e)
【程序分析】本程序定义两个字符型变量a、b,并初始化赋值,输出两个字符。在cout语句中输出三个转义字符。
在Visual Studio 2017中的运行结果如图4-6所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P57_9015.jpg?sign=1739410739-nPaPdwjIRgz34ee9dhhrwOLAdFpLk45o-0-4efb4eb43725226077b5b81769f0ff24)
图4-6 字符类型
4.2.3 宽字符类型(wchar_t)
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P57_9018.jpg?sign=1739410739-XtwX7pbCwx7wMrx008yOSMaSgohoGhy5-0-9782d495de69926460f4df599c28783f)
char类型的常见编码方式是ASCII。ASCII编码是一种基于8位二进制数的字符编码算法,是美国ANSI制定的一种单字符编码方案,能表示256种可能的字符,常见的字母、符号、键盘指令等,全能用ASCII码表示,而由于ASCII码是基于8位的编码,因此用这种算法的编译器,char类型都占8位。
注意:因为用了ASCII,所以char才是8位,而不是char是8位,所以采用ASCII。
wchar_t的出现,是出于程序兼容多语言的需求,因为在很多语言中,字符的数量远远大于256,因此需要把原字符进行扩容,以便能表示更多的字符类型。wchar_t全称是wide character type,也就是宽字符。
标准C++中的wprintf()函数以及iostream类库中的类和对象能提供wchar_t宽字符类型的相关操作。
4.2.4 浮点数类型
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P57_9019.jpg?sign=1739410739-W39YItlmCnTWKJ3wqcIjffmhPldPHtKp-0-67b5d45e867b8557f27c6183a24011b4)
浮点数类型变量又称为实型,它是由整数部分和小数部分组成的。实型变量用于存储实型数值的变量,根据精度可分为单精度类型、双精度类型以及长双精度类型3种。
浮点数类型数据的类型说明以及取值范围见表4-6。
表4-6 浮点型数据的类型说明以及取值范围
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-T58_71532.jpg?sign=1739410739-axUS2reLuwJt30qEa7nDzV5H20DR0q4l-0-e639872e5bdbd8857ac27190ab868e70)
1. 单精度类型
单精度类型使用关键字float表示,它占有4字节内存,取值范围为-3.4*10-38~3.4*1038。单精度类型变量的定义语法如下:
float 变量名;
例如,定义一个单精度类型变量a,初始化为1.11,语法如下:
float a=1.11f;
2. 双精度类型
双精度类型使用关键字double表示,它占有8字节内存,取值范围为-1.7*10-308~1.7*10308。双精度类型变量的定义语法如下:
double 变量名;
例如,定义一个双精度类型变量b,初始化为2.234,语法如下:
double b=2.234;
3. 长双精度类型
长双精度类型使用关键字long double表示,它占有8字节内存,取值范围为-1.7*10-308~1.7*10308。长双精度类型变量的定义语法如下:
long double 变量名;
例如,定义一个长双精度类型变量c,初始化为3.345,语法如下:
long double c=3.345;
4.2.5 布尔类型(bool)
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P58_9208.jpg?sign=1739410739-hDddGcYcSoWoMvBidJVc5uLD7Pj1eUD9-0-7c79c8510208a39f630c1b7a0b8ffaa4)
布尔类型只有两个值false和true。布尔类型通常用来判断条件是否成立,如果变量值为0表示假,并且可以赋予文字值false;变量值为非0表示真,可以赋予文字值true。
【例4-2】编写程序,定义bool类型的变量,并对其进行判断。
(1)在Visual Studio 2017中,新建名称为“4-2.cpp”的Project2文件。
(2)在代码编辑区域输入以下代码。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P58_71540.jpg?sign=1739410739-2pvppjEcbPAcjHMwUC5Gdy18EV2qY1HW-0-2132a24032b7d5a46784e18c18c38f6c)
【程序分析】本例中定义了一个bool类型的变量x,并赋值为2。因为2是非零值,所以语句“bool x=2;”等效于“bool x=true;”。因此if语句表示,x非零则输出“正确”。执行表达式“x=x-1;”语句时,bool类型的数据true参与算术运算,其值会转为一个整数值1,所以减1后结果为0,赋给x时会转换为bool值false。执行if语句时,x的值是0。所以不输出“错误”。
在Visual Studio 2017中的运行结果如图4-7所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9366.jpg?sign=1739410739-CAbgtSGFhIbLtJUIu0GBLYDYioy6VJPe-0-9d33a362bbac2be2f84a19a36becbebb)
图4-7 bool类型变量
当表达式需要一个算数值时,布尔类型对象将被隐式地转换成int类型也就是整型对象,false就是0,true就是1。
【例4-3】编写程序,输出bool类型变量的值。
(1)在Visual Studio 2017中,新建名称为“4-3.cpp”的Project3文件。
(2)在代码编辑区域输入以下代码。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9379.jpg?sign=1739410739-C6EeU9bbCTP0SMbx4n63aUSeSH8s0mkZ-0-ebd33f26a6f6639ec178b6bfaa2234cc)
【程序分析】本例定义bool类型的变量x和y,分别赋值为true和false,并输出它们的值。
在Visual Studio 2017中的运行结果如图4-8所示。
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9374.jpg?sign=1739410739-J1ncQOybULMs4UO4pGKuvITqkdscvR7Z-0-1920c82f925f7c1f80219e673114cec1)
图4-8 bool类型
4.2.6 无类型(void)
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9377.jpg?sign=1739410739-P3TMtu10QHnaJ1bEjwMdYSaDZdbrt2BB-0-6381c69c34abd4e93bbf5e888b4cc2d5)
无类型就是空类型,放在函数前面,表示该函数不返回任何值,放在函数参数部分,表示函数不传入参数。
例如:
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9380.jpg?sign=1739410739-M3euKAGVxQ9ycBmjpTLEuCio14i0Z1J2-0-a79d2c027da60b89613d9f9054fe99bd)
注意:void不能代表一个真实的变量。
下面代码都企图让void代表一个真实的变量,因此都是错误的代码:
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P59_9381.jpg?sign=1739410739-pSJynJwvDhCpYMXvhQD6bZMVnWimq9Ry-0-40ad32995d46520a27fd0f79e86bc123)
空类型在调用函数值时,通常应向调用者返回一个函数值。这个返回的函数值是具有一定的数据类型的,应在函数定义及函数说明中给以说明,但是,也有一类函数,调用后并不需要向调用者返回函数值,这种函数可以定义为“空类型”。其类型说明符为void。
之所以需要空类型,是因为函数的默认返回值类型是int,如果在函数定义时未带返回类型说明,则默认为int;即使函数中没有return语句,编译器按照函数返回值的原理,会返回一个不确定的值。如果将这样的函数错用在表达式里,语法上没错,但会带来很难察觉的逻辑错误。而将空类型函数用在表达式里是一个编译错误。
4.2.7 对齐
![](https://epubservercos.yuewen.com/F7D2C7/15289822205524706/epubprivate/OEBPS/Images/Figure-P60_9429.jpg?sign=1739410739-zfx2s2TZOMrWEW5F3vnqBqxDSAtjvTME-0-3b3c3143d0376f5680f99daae45068a6)
现代计算机中内存空间都是按照字节划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序地一个接一个地排放,这就是对齐。32位机器上各数据类型的长度为:char为1字节、short为2字节、int为4字节、long为4字节、float为4字节、double为8字节。
1. 对齐的意义
在不同编译平台或处理器上,字节对齐会造成消息结构长度的变化。编译器为了使字节对齐可能会对消息结构体进行填充,不同编译平台可能填充为不同的形式,这样会大大增加处理器间数据通信的风险。所以对于本地使用的数据结构,为提高内存访问效率,采用四字节对齐方式;同时为了减少内存的开销,会合理安排结构体成员的位置,减少四字节对齐导致的成员之间的空隙,提高内存的存取效率。如果在不同平台之间传递二进制流,那么在这两个平台间必须要定义相同的对齐方式,不然莫名其妙地出了一些错,可是很难排查的。
2. 对齐的实现
通常,在写程序的时候,不需要考虑对齐问题,编译器会自动选择适合目标平台的对齐策略。当然,也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法,比如写入预编译指令#pragma pack(),即告诉编译器按两字节对齐。
整个程序在给每个变量进行内存分配时都会遵循对齐机制,也都会产生内存空间的浪费。但是,这种浪费是值得的,因为它换来的是效率的提高。