【c++】【基础】【primer_plus】【第三章】基本数据类型
变量命名规则
变量由字母、数字、下划线组合而成,不能有空格。
数字不能开头。
下划线开头的一般为系统专用全局变量变量,两个下划线开头的一般给编译器使用。
字母区分大小写。
不能是c/c++语言的关键字。
长度不超过31个字符(c89)标准,c99为63个。
整型
所有用来表示整数的数据类型都称为整型。整型分为有符号整型和无符号整型。其中无符号整型前面需加unsigned
关键字。
1 | unsigned int a = 10; |
长度
整型的长度在不同的操作系统中都有可能不同,所以c++采用了一种灵活的标准。
类型 | 位数 |
---|---|
short | 至少16位 |
int | 至少和short一样长 |
long | 至少32位, 且至少和int一样长 |
long long | 至少64位, 且至少和long一样长 |
例如其在各个位数的操作系统上的长度如下表所示,其中长度单位为字节(8位二进制位)。
类型 | 16位操作系统 | 32位操作系统 | 64位操作系统 |
---|---|---|---|
short | 2 | 2 | 2 |
int | 2 | 4 | 4 |
long | 4 | 4 | 8 |
long long | 8 | 8 | 8 |
最值
我们可以使用<climits>
头文件获得整型的最值信息。可使用以下宏定义获得各种整型类型的大小。
1 | SHRT_MAX SHRT_MIN |
我们使用sizeof(int)
获得某个类型(这里以int
型为例)的字节数。另外,对变量名使用sizeof()
函数时,可以不用括号,如sizeof a
。
我们使用CHAR_BIT
宏来获得当前操作系统一个字节占多少位,一般为8位。
选择
在所有的整型类型中,int
是最自然的选择了,大部分操作系统的int
都是4字节的,而不用专门进行4字节对齐(可参考操作系统相关知识了解字节对齐的好处),处理效率最高。
有时候,short
也是不错的选择,如果你能保证你的数据集没有很大的数。如果此时恰好你需要存储特别多的这种不很大的数,使用short
无疑会帮你节省大量的内存。
long
类型的可移植性比较高,如果你要为数据将来的发展或移植考虑,如将原来在32位上跑的程序移植到64位上来,那么请直接使用long
吧。
long long
用来处理更大的数值,如果你打过acm竞赛就会发现,有些题目的中间结果(比如在取模之前)不用long long
还真的是存不下。
有些时候我们把char
类型(字符类型)也归为整型,因为它对应着[0,255]区间内的整数,它只占有一个字节,所以比short更节省内存,在某些特殊的情况下也是最好的选择。
后缀
我们使用后缀来表示一个字面量到底属于哪种类型,没有后缀的一般都为int
型。如2L
表示long
型数值2
。
具体的整型后缀表如下所示。
类型 | 后缀 |
---|---|
long | L |
unsigned long | uL |
unsigned long long | uLL |
进制
一般我们显示的数值为十进制数,但是c++也可以显示八进制、十六进制的数值。
其中八进制的数据我们一般使用0
作为前缀,且保证后面的每一位数不能大于7。而十六进制使用0x
作为前缀,且后面每一位数可以使用0~9a~f
来表示。
1 | // 十进制(decimal) |
char
char
类型为单字节字符,表示某一个字符,它将字符与其ascii
码相对应。
char
类型默认为unsigned char
,取值范围为[0,255]。但是也可显示声明为signed char
,取值范围变为[-128, 127]。
下面是一个关于char
的示例程序。
1 |
|
其输出结果如下。
1 | M - 77 |
转义序列
我们使用转义序列来表示字符或者字符串(可以理解为由字符串起来的句子)中难以表达的字符,比如我们使用\n
来表示回车。部分转义字符如下表所示。
字符含义 | 转义序列 |
---|---|
换行 | |
回车 | |
水平制表 | |
垂直制表 | |
退格 | |
响铃 | |
问号 | ? |
反斜线 | \\ |
单引号 | ' |
双引号 | " |
c++使用反斜线\
作为转义标记。可以想像一下,在c++内部解析一串字符时,当碰到\
时,它便会从一张转义字符表中查找有没有与\
后面的字符完全吻合的转义序列,如果有的话,则转换其意义之后再输出。这也是为什么看似稀松平常的\
在字符串中出现时也需要转义成\\
才能输出。
通用字符名
为了可以统一显示世界各地各种千奇百怪闻所未闻的字符,c++采用了一种通用字符名的广宁,它可以显示所有iso10646
标准规定的所有unicode
字符。其显示方法有以下两种。
4个十六进制位(16位),如
\u006E
。8个十六进制位(32位), 如
\U0000222B
。
如下面语句。
1 | cout << "k\u00E2rper" << endl; -- k芒rper |
宽字符类型
宽字符也是为了显示更多或者更完整的字符,所以一般会使用更多的空间,如2字节、4字节等。
wchar_t
wchar_t
类型的字符串以L
作为前缀,一般占用2个字节,且有专门的输入输出处理api,如下代码所示。
1 | wchar_t wch = L 'P' ; // 使用前缀L表示 |
char16_t和char32_t
chara16_t
与char32_t
都是宽类型的字符,一个占16位,一个占32位,如下代码所示。
1 | char16_t ch1 = u'\u00F6'; // 无符号 16位 |
bool 型
进行逻辑运算的数据类型。
1 | bool flag = true; // 任何非零值 |
浮点型
浮点型在计算机中用来表示小数,它的存储方式(可参考计算机组成原理相关知识),存储大小,以及书写格式等与整型都存在较大的区别。
书写格式
标准小数点表示法如下所示。
1 | 0.023 |
E表示法如下所示。
1 | 3.45E8 |
有效位与取值范围
在IEEE754浮点数表示法
里,浮点数的存储分为三个部分,如下所示。
逐点类型 | 总位数 | 符号位(决定正负) | 指数位(决定范围) | 尾数位(小数部分) |
---|---|---|---|---|
float | 32(至少32) | 1 | 8 | 23 |
double | 64(至少48,不少于float) | 1 | 11 | 52 |
long double | 128(不少于double) | 1 | 15 | 112 |
其中指数位可决定取值范围,而尾数位决定有效数字(精度)。下面以float
为例详细说明。
float
的指数位为8位,所以指数的范围为[-127,128],则float
的取值范围为 \(\[-2^{-128},2^{128}\]\),此取值范围与正整数有关,可认为负整数无限趋近于0.0了。转换为10进制即为\(\[-3.4\times10^{38},3.4\times10^{38}\]\)。
float
的尾数位为23,则\(2^{23}=8388608\),总共7位,但不能保证所有的7位尾数都是精确的(大于8366608的不精确),所以float
的有效数字位数为6~7位
。
下面为一使用浮点数的示例代码。
1 |
|
输出结果如下。
1 | a = 3.333333 |
浮点后缀
浮点类型 | 后缀 | 示例 |
---|---|---|
float | F/f | 1.234f 1.234F |
double | 默认类型,无后缀 | 1.234 |
long double | L/l | 1.234L 1.234l |
算术运算符
基本运算符
+ 加法。
- 减法。
* 乘法。
/ 除法。两个操作数都是整数时结果才为整数。
% 求模。两个操作数必须是整数。
优先级
先乘除(取模),后加减。
可用括号控制优先级。
读者可自行搜索c++运算符优先级表,后续本站也会更新优先级相关资料。
结合性
结合性意为两个优先级相同的运算符被同时用于一个操作数时,需要考虑是左结合还是右结合。
如下代码所示,会从左往右进行计算,因为对于4而言,除法/
和乘法*
处于同一优先级,但是左结合性的,所以从左往右计算。
1 | 120/4*5 = 150; |
类型转换
自动类型转换
大范围转小范围(long->int或float->int等)会丢失精度。
初始化时或将一种类型赋值给另一种类型时自动转换。
表达式中包含不同类型时,会出现整型提升,即小范围的类型变为大范围的类型。
参数传递给函数时会发生自动类型转换。
以{}初始化(列表初始化)时,不允许缩窄(float->int),这是c++11的新规定。
强制类型转换
1 | (typename)value; // C语言格式 |
auto初探
auto
数据类型是c++11新标准定义的数据类型,它可以根据上下文语境自动推断数据类型(如果可以的话)。这在某些时候会给我们写代码时提供极大的便得,甚至实现更强大的功能。
最常见的例子是使用STL
(标准模板库,以后会讲到)时迭代元素更加方便,更具有泛型的思想。如下代码所示。此处只作了解,以后会仔细分析auto
更详细的用法及原理。
1 | vector<int> x; |
可简化为如下代码。
1 | vector<int> x; |