位、字节和内存寻址
在第1.3课 — 对象和变量简介中,我们提到变量是内存中一块区域的名称,可用于存储信息。简要回顾一下,计算机有随机存取存储器(RAM),供程序使用。定义变量时,会为该变量分配一块内存。
内存的最小单位是二进制位(也称为位),其值可以是0或1。你可以把位想象成传统的电灯开关 —— 要么灯是关的(0),要么灯是开的(1)。没有中间状态。如果你查看一段随机的内存,你看到的只是……011010100101010……或类似的组合。
内存地址和组织
内存被组织成称为内存地址(简称地址)的连续单元。就像可以通过街道地址找到某条街上的特定房子一样,内存地址允许我们找到并访问特定位置的内存内容。
或许令人惊讶的是,在现代计算机架构中,每个位并没有自己的唯一内存地址。这是因为内存地址的数量是有限的,而且按位访问数据的需求很少。相反,每个内存地址存储1个字节的数据。字节是一组按单元操作的位。现代标准是字节由8个连续位组成。
关键见解
在C++中,我们通常处理"字节大小"的数据块。
下面的图片展示了一些连续的内存地址以及对应的字节数据:
内存寻址
顺便说一下……
有些较旧的或非标准的机器可能有不同大小的字节(从1到48位) —— 然而,我们通常不需要担心这些,因为现代事实上的标准是字节为8位。在这些教程中,我们将假设字节是8位。
数据类型
因为计算机上的所有数据都只是一系列位,所以我们使用数据类型(通常简称为类型)来告诉编译器如何以有意义的方式解释内存内容。你已经见过一个数据类型的例子:整数。当我们声明一个变量为整数时,我们是在告诉编译器"这个变量使用的内存部分将被解释为整数值"。
数据类型的工作原理
当你给一个对象赋值时,编译器和CPU会负责将你的值编码成该数据类型对应的位序列,然后存储在内存中(记住:内存只能存储位)。例如,如果你给一个整数对象赋值为65,该值会被转换成位序列0100 0001,并存储在分配给该对象的内存中。
相反,当对象被评估以产生一个值时,该位序列会被重新转换回原始值。也就是说,0100 0001会被转换回值65。
幸运的是,编译器和CPU在这里做了所有艰苦的工作,所以你通常不需要担心值是如何转换成位序列以及如何转换回来的。
你所需要做的就是为你的对象选择一个最适合你期望用途的数据类型。
基本数据类型
C++语言提供了许多预定义的数据类型供你使用。其中最基本的就是基本数据类型(非正式地有时也称为基本类型或原始类型)。
以下是基本数据类型列表,其中一些你已经见过:
类型 | 类别 | 含义 | 示例 |
---|---|---|---|
float | 浮点型 | 带小数部分的数字 | 3.14159 |
double | 浮点型 | 带小数部分的数字 | 3.14159 |
long double | 浮点型 | 带小数部分的数字 | 3.14159 |
bool | 整型(布尔) | 真或假 | true |
char | 整型(字符) | 单个文本字符 | ‘c’ |
wchar_t | 整型(字符) | 单个文本字符 | ‘c’ |
char8_t (C++20) | 整型(字符) | 单个文本字符 | ‘c’ |
char16_t (C++11) | 整型(字符) | 单个文本字符 | ‘c’ |
char32_t (C++11) | 整型(字符) | 单个文本字符 | ‘c’ |
short int | 整型(整数) | 包括0的正负整数 | 64 |
int | 整型(整数) | 包括0的正负整数 | 64 |
long int | 整型(整数) | 包括0的正负整数 | 64 |
long long int (C++11) | 整型(整数) | 包括0的正负整数 | 64 |
std::nullptr_t (C++11) | 空指针 | 空指针 | nullptr |
void | 无类型 | 无类型 | n/a |
本章致力于详细探讨这些基本数据类型(除了std::nullptr_t,我们会在讨论指针时讲到它)。
整数与整型
基本概念
在数学中,“整数"是没有小数或分数部分的数,包括负数、正数和零。术语"整型"有几种不同的含义,但在C++的上下文中,它被用来表示"像整数一样”。
C++中的整型定义
C++标准定义了以下术语:
- 标准整数类型是短整型(short)、整型(int)、长整型(long)、长长整型(long long)(包括它们的有符号和无符号变体)。
- 整型包括布尔类型(bool)、各种字符类型(char类型)和标准整数类型。
- 所有整型在内存中都以整数值存储,但只有标准整数类型在输出时会显示为整数值。
C++标准还明确指出"整数类型"是"整型"的同义词。然而,按照惯例,“整数类型"更多地被用作"标准整数类型"的简写。
注意:整型只包括基本类型。这意味着非基本类型(如枚举类型(enum)和枚举类(enum class))不是整型,即使它们以整数形式存储。
其他类型的集合
C++包含三组类型:
- 基本数据类型:语言内置的最基本和最必要的数据类型。
- 复合数据类型:提供更复杂的数据类型,允许创建自定义类型(将在第12.1课介绍)。
- 标准库类型:由C++标准库提供,需要包含适当的头文件。
关于字符串
值得注意的是,基本类型中没有用于处理字符串的数据类型。这是因为在现代C++中,字符串是标准库的一部分。我们会在下一章(第5.7课 — std::string简介)中介绍字符串。
_t后缀说明
许多在C++新版本中定义的类型(例如std::nullptr_t
)使用_t后缀。这个后缀表示"类型”,是现代类型常用的命名法。
提示:如果你看到带有_t后缀的东西,它可能是一个类型。但许多类型没有_t后缀,所以这种用法并不一致。