位、字节和内存寻址
在第 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 double long double | 浮点数 | 带小数部分的数字 | 3.14159 |
bool | 整型 (布尔型) | 真或假 | true |
char wchar_t char8_t (C++20) char16_t (C++11) char32_t (C++11) | 整型 (字符型) | 单个文本字符 | ‘c’ |
short int int long int long long int (C++11) | 整型 (整数型) | 正负整数,包括 0 | 64 |
std::nullptr_t (C++11) | 空指针 | 一个空指针 | nullptr |
void | 空 | 无类型 | 不适用 |
本章致力于详细探讨这些基本数据类型(除了 `std::nullptr_t`,我们将在讨论指针时讨论它)。
整数类型与整型
在数学中,“整数”是没有小数或分数部分的数字,包括负数、正数和零。“整型”一词有几个不同的含义,但在 C++ 的上下文中,它表示“类似整数的”。
C++ 标准定义了以下术语
- 标准整数类型是 `short`、`int`、`long`、`long long`(包括它们的有符号和无符号变体)。
- 整型是 `bool`、各种 `char` 类型和标准整数类型。
所有整型都以整数值存储在内存中,但只有标准整数类型在输出时会显示为整数值。我们将在各自的课程中讨论 `bool` 和 `char` 类型在输出时的表现。
C++ 标准还明确指出“整数类型”是“整型”的同义词。然而,习惯上,“整数类型”更多地用作“标准整数类型”的简称。
另请注意,“整型”一词仅包含基本类型。这意味着非基本类型(例如 `enum` 和 `enum class`)不是整型,即使它们存储为整数(并且在 `enum` 的情况下,也显示为整数)。
其他类型集
C++ 包含三组类型。
前两个是语言本身内置的(不需要包含头文件即可使用)
- “基本数据类型”提供了最基本和必不可少的数据类型。
- “复合数据类型”提供了更复杂的数据类型,并允许创建自定义(用户定义)类型。我们在第 12.1 课——复合数据类型介绍中介绍这些。
基本类型和复合类型之间的区别并不是那么有趣或相关,所以通常可以认为它们是单一的类型集。
第三组(也是最大的一组)类型由 C++ 标准库提供。由于标准库包含在所有 C++ 发行版中,因此这些类型广泛可用并已标准化以确保兼容性。使用标准库中的类型需要包含相应的头文件并链接标准库。
命名法
“内置类型”一词最常被用作基本数据类型的同义词。然而,Stroustrup 和其他人使用该词来表示基本和复合数据类型(两者都内置于核心语言中)。由于该词定义不明确,我们建议相应地避免使用它。
上表中基本类型的一个显著遗漏是用于处理字符串(通常用于表示文本的字符序列)的数据类型。这是因为在现代 C++ 中,字符串是标准库的一部分。尽管本章我们将重点关注基本类型,但由于基本字符串用法简单实用,我们将在下一章(在第 5.7 课——std::string 介绍中)介绍字符串。
_t 后缀
C++ 新版本中定义的许多类型(例如 `std::nullptr_t`)都使用 _t 后缀。这个后缀的意思是“type”(类型),这是现代类型中常见的命名约定。
如果你看到带有 _t 后缀的东西,它很可能是一个类型。但是很多类型没有 _t 后缀,所以这并没有被一致地应用。