第二章 变量和基本内置类型
概览
内容有点多,所以把导图拆开方便阅读。
小节完整版请拖至小节末尾;
本章完整版请拖至文章末尾。
2.1 基本内置类型
2.1.1基本数据类型
类型 | 含义 | 大小 |
---|---|---|
bool | 布尔类型 | 未定义 |
char | 字符 | 8位 |
wchar_t | 宽字符 | 16位 |
char16_t | Unicode字符 | 16位 |
char32_t | Unicode字符 | 32位 |
short | 短整型 | 16位 |
int | 整型 | 16位 |
long | 长整型 | 32位 |
long long | 长整型 | 64位 |
float | 单精度浮点数 | 6位有效数字 |
double | 双精度浮点数 | 10位有效数字 |
long double | 扩展精度浮点数 | 10位有效数字 |
Tips1:如何选择类型
关于如何选择类型的一些准则
- 知道数据不可能为负的情况,用unsigned。
- 若int范围不够用,跳过long(long一般和int有一样的尺寸),直接选用long long。
- 在算数表达式中不要使用char或者bool,只有在存放字符或布尔值时才使用它们。因为不同机器对char是有符号还是无符号的解释可能不一样。若有需要,请使用signed char或者unsigned char。
- 浮点数直接用double,没必要用float(float精度不够,而且双精度浮点数和单精度浮点数的计算代价相差无几)。
2.1.2类型转换
Tips2:避免无法预知和依赖于环境的行为
无法预知的行为源于编辑器无需(有时是不能)检测的错误。即使代码编译通过了,如果程序执行了一条未定义的表达式,仍有可能产生错误。
不幸的是,在某些情况和/或某些编译器下,含有无法预知行为的程序也能正确执行。但我们无法保证同样一个程序在别的编译器下也能正常工作,针织已经编译通过的代码再次执行也可能会出错。此外,也不能认为这样的程序对一组输入有效,对另一组就一定有效。
程序也应该尽量避免依赖于实现环境的行为。如果我们把int尺寸看成是一个确定不变的已知值,那么这样的程序就称作不可移植的(nonportable)。当程序移植道别的机器上后,依赖于实现环境的程序就有可能发生那个错误。要从过去的代码中定位这类错误可不是一件轻松愉快的工作。
2.1.3字面值常量
前缀 | 含义 | 类型 |
---|---|---|
u | Unicode16字符 | char16_t |
U | Unicode32字符 | char32_t |
L | 宽字符 | wchat_t |
u8 | UTF-8(仅用于字符串字面常量) | char |
后缀 | 最小匹配类型 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
后缀 | 类型 |
---|---|
f or F | float |
l or L | long double |
2.2 变量和基本类型
2.2.1变量定义
Tips3 未初始化变量引发运行时故障
未初始化的变量含有一个不确定的值,使用未初始化变量的值是一种错误的编程行为并且很难调试。尽管大多数编译器都能对一部分使用未初始化变量的行为提出警告,但严格来说,编译器并未被要求检查此类错误。
使用未初始化的变量将带来无法预计的后果。有时我们足够幸运,一访问此类对象程序就崩溃并报错,此时只要找到崩溃的位置就很容易发现变量没被初始化的问题。另外一些时候,程序会一直执行完并产生错误的结果。更糟糕的情况是,程序结果时对时错、无法把握。而且,往无关的位置添加代码还会导致我们误以为程序对了,其实结果仍旧有错。
建议初始化每一个内置类型的变量。虽然并非必须这么做,但如果我们不能确保初始化后程序安全,那么这么做不失为一种简单可靠的方法。
2.2.2变量定义和声明的关系
关键概念:静态类型
C+是一种 静态类型(statically typed) 语言,其含义是在编译阶段检查类型。其中,检查类型的过程称为类型检查(type checking)。
我们已经知道,对象的类型决定了对象所能参与的运算。在C++语言中,编译器负责检查数据类型是否支持要执行的运算,如果试图执行类型不支持的运算,编译器将报错并且不会生成可执行文件。
程序越复杂,静态类型检查越有助于发现问题。然而,前提是编译器必须知道每个实体对象的类型,这就要求我们在使用某个变量之前必须声明其类型。
2.2.3标识符
2.2.4名字的作用域
#include<iostream>
using namespace std;
//该程序仅用于说明:函数内部不宜定义与全局变量同名的新变量
int reused=42;//resused拥有全局作用域
int main()
{
int unique = 0; //unique拥有块作用域
//输出#1:使用全局变量reused;输出 42 0
cout << reused << " " << unique << endl;
int reused = 0;//新建局部变量reused,覆盖了全局变量reused
//输出#2:使用局部变量reused;输出 0 0
cout << reused << " " << unique << endl;
//输出#3:显式访问全局变量reused;输出 42 0
cout <<:: reused << " " << unique << endl;
return 0;
}
2.3复合类型
待更新