指针与数组

数据类型

在 C 中,指针是一种数据类型,数组也是一种数据类型,而且是一种和指针密切相关的数据类型。

作为一门静态强类型的编程语言,C 还很傲娇地宣称「数组」是一种派生类型。

为何?

我先列出目前拥有的知识点:

所有内存都要尽可能地回收,以便造成程序拥有无限内存的假象。

那在 C 语言中,我们知道通过 malloc 函数分配内存,都过 free 函数释放内存。可是我们自己声明的变量,比如 int ,long 之类的,它们并没有通过 malloc 分配内存,也没有通过 free 释放内存。那这些内存是怎么释放掉的呢?

这也就是最有意思的地方了:这类变量通常比较少,而且占用内存空间通常比较少,而且生命周期还短。所以,这类变量随函数的递推被创建,随函数的回归被销毁。销毁很容易,其实就是简单的丢弃。不在函数栈内的就被认为是可用空间。因为这样子,函数栈内不同栈帧内部的变量有各自独立的运行环境,所以完全可以同名。就像北村和南庄可以各有一个王二一样,并不会引起混淆。

有意思的问题是:这个创建和销毁变量的过程,在理论上完全可以使用于所有变量类型,但为什么还要对一些变量进行特殊的区分对待呢?

理论上确实可以通用,但程序运行期间,经常会同时维护并操作大量数据,占用空间,而且耗时。

在函数栈的模型中,函数栈帧之间只能通过复制数据进行消息传递和回馈。如果所有数据都存在函数栈帧内部,那么函数栈可能会很大,不同的函数栈里可能会出现大量重复数据,就像克隆了北村里九成村民放到南庄一样。

这在现实中当然是行不通的。

所以就需要其他的实现方式。

其实很自然,我们在寄存器中维护函数栈,使用的是地址索引。同样的,在函数栈帧中维护大量数据,也可以使用地址索引。

这就是指针的中枢作用所在。

再想想,那么数组呢?数组似乎也可以很大,但是貌似也没有使用 malloc 和 free 。而我们知道,数组的名字所代表的变量其实就是指针变量,通过这个指针变量索引数组元素。

既然没有使用 malloc ,数组的创建和销毁具体如何实现,就不再是我们 C 语言的用户所能控制的了,我们可以猜测,猜的对不对甚至都不再重要,大部分时候。这也是抽象的好处吧。

字符串其实是一种特殊的字符数组

在英语国家里,只有二十六个字母,外加其他一些符号。一个字节完全可以有足够的表示能力来表征它们。换句话说,一个个字符可以用编码好的一个个字节来表示,在特定的上下文中,一个个字节,一个个二进制数,就可以表示字符。

只是后来,互联网国际化以后,单字节绝对不够用,各国一开始是自行解决,后来才慢慢开始统一标准。

指针自指,数组自包含

指针指向其他变量,而指针本来就是一种变量,所以指针可以指向指针。

数组是一系列同类型变量,而数组也可以作为一个同类型变量成一系列,所以就有了数组的数组。

同理,可以有一个指向「指向指针的指针」的指针,也可以有一个「数组的数组」的数组。

数组是序列,而指针才是组织起所有数据的中枢,函数本来也是数据。

所以,C 程序就是由指针组织起来的,就像指针组织起机器代码一样。


不知是该恭喜,还是该怎样,总之阅读到该文的,你是第 人。每一次刷新,都是不同的自己。