我们之所以需要指针,主要是由 C 语言中函数的工作方式决定的。C 语言函数的参数全部是通过值传递的。也就是说,传递给函数的实际是实参的拷贝。对于 、longchar等系统类型以及用户自定义的结构体都是成立的。这种方式适用于绝大多数情况,但也会偶尔出现问题。

    一种常见的情况是,如果我们有一个巨大结构体需要作为参数传递,则每次调用函数,就会对实参进行一次拷贝,这无疑是对性能和内存的浪费。

    为了解决这个问题,C 语言的开发者们想出了一个聪明的办法。他们把内存想象成一个巨大的字节数组,每个字节都可以拥有一个全局的索引值。这有点像门牌号:第一个字节索引为 0,第二个字节索引为 1,等等。

    在这种情况下,计算机中的所有数据,包括当前运行的程序中的结构体、变量都有相应的索引值与其对应(数据的开始字节的索引作为整个数据的索引)。所以,除了将数据本身拷贝到函数参数,我们还可以只拷贝数据的索引值。在函数内部则可以根据索引值找到需要的数据本身(译者注:我们将这个索引值称为地址,存储地址的变量称为指针)。使用指针,函数可以修改指定位置的内存而无需拷贝。除此之外,指针还可以做其他很多事情。

    所以,所谓的指针也仅仅是一个数字而已。是内存中的一块数据的开始字节的索引值。指针的类型用来提示程序员和编译器指针指向的是一块什么样的数据,占多少个字节等。

    指针类型是在现有类型的后面加一个星号组成,我们之前已经见过一些指针的示例了,如:mpc_parser_t*、 以及 char*

    最后,为了获取指针所指向的地址的数据值(称为解引用),我们需要在指针左边使用 * 操作符。要获取结构体指针的某个字段,需要使用 -> 操作符,而不是 .,这你在第七章已经见过了。