指针:为什么?
想象一下,您想创建一个**文本编辑器**——一个让您编辑普通 ASCII 文本文件的程序,就像 UNIX 上的“vi”或 Windows 上的“记事本”一样。文本编辑器是人们经常创建的程序,因为仔细想想,文本编辑器很可能是程序员最常用的软件。文本编辑器是程序员与计算机的紧密联系——您在这里输入所有的想法并对其进行操作。显然,对于您经常使用并密切协作的任何事物,您都希望它尽善尽美。因此,许多程序员会创建自己的编辑器并根据其个人工作风格和偏好进行定制。
所以有一天,您坐下来开始开发您的编辑器。在考虑了所需功能之后,您开始思考编辑器的“数据结构”。也就是说,您开始考虑如何将您正在编辑的文档存储在内存中,以便您可以在程序中对其进行操作。您需要一种方法来存储您正在输入的信息,并使其能够快速、轻松地进行操作。您认为一种方法是按字符行来组织数据。根据我们目前所讨论的,您目前唯一可用的就是数组。您想:“嗯,一个典型的行长 80 个字符,一个典型的文件不超过 1,000 行。”因此,您声明了一个**二维数组**,如下所示
广告
char doc[1000][80];
这个声明请求一个包含 1,000 行 80 个字符的数组。这个数组的总大小为 80,000 个字符。
然而,当您更深入地思考您的编辑器及其数据结构时,您可能会意识到三件事
- 有些文档是长列表。每行都很短,但有数千行。
- 一些特殊用途的文本文件有很长的行。例如,某个数据文件可能包含 542 个字符的行,每个字符代表 DNA 片段中的氨基酸对。
- 在大多数现代编辑器中,您可以同时打开多个文件。
假设您将同时打开的文件数设置为最多 10 个,最大行长为 1,000 个字符,最大文件大小为 50,000 行。您的声明现在看起来像这样
char doc[50000][1000][10];
这看起来并非不合理,直到您拿出计算器,将 50,000 乘以 1,000 再乘以 10,然后意识到这个数组包含 5 亿个字符!如今大多数计算机都无法处理如此大小的数组。它们根本没有足够的 RAM,甚至没有足够的 虚拟内存 空间来支持如此大的数组。如果用户尝试在即使是最大的多用户系统上同时运行三到四个此程序的副本,这将给系统设施带来巨大的压力。
即使计算机接受了如此大数组的请求,您也会发现这是对空间的极大浪费。声明一个 5 亿个字符的数组似乎很奇怪,因为在绝大多数情况下,您会运行这个编辑器来查看最多占用 4,000 或 5,000 字节的 100 行文件。数组的问题在于,**您必须从一开始就声明它在每个维度上都具有其最大大小。** 这些最大尺寸通常会相乘形成非常大的数字。此外,如果您碰巧需要编辑一个包含 2,000 个字符行的特殊文件,那您就束手无策了。您实际上无法预测和处理文本文件的最大行长,因为从技术上讲,这个数字是无限的。
指针就是为了解决这个问题而设计的。有了指针,您可以创建**动态数据结构**。您不必在数组中预先声明最坏情况下的内存消耗,而是可以在程序运行时从**堆**中**分配**内存。这样,您就可以使用文档所需的精确内存量,而不会造成浪费。此外,当您关闭文档时,可以将内存返回到堆中,以便程序的其他部分可以使用它。有了指针,内存可以在程序运行时被回收利用。
顺便说一下,如果您阅读了之前的讨论,并且您最大的疑问之一是“字节到底是什么?”,那么文章 位和字节的工作原理 将帮助您理解这些概念,以及“兆”、“千兆”和“太拉”等内容。去看看吧,然后回来。