指针基础
要理解指针,将其与普通变量进行比较会有所帮助。
“普通变量”是内存中可以保存值的一个位置。例如,当你将变量 i 声明为整数时,内存中会为其预留四个字节。在你的程序中,你通过名称 i 来引用内存中的该位置。在机器层面,该位置有一个内存地址。该地址上的四个字节对你(程序员)来说是 i,这四个字节可以保存一个整数值。
广告
指针是不同的。指针是一个指向另一个变量的变量。这意味着指针保存了另一个变量的内存地址。换句话说,指针不以传统意义保存值;相反,它保存的是另一个变量的地址。指针通过保存另一个变量的地址副本“指向”该变量。
由于指针保存的是地址而不是值,它由两部分组成。指针本身保存地址。该地址指向一个值。有指针,也有被指针指向的值。在你熟悉它之前,这个事实可能会有点令人困惑,但一旦你熟悉了它,它就会变得极其强大。
以下示例代码展示了一个典型的指针
#include <stdio.h> int main() { int i,j; int *p; /* a pointer to an integer */ p = &i; *p=5; j=i; printf("%d %d %d\n", i, j, *p); return 0; }
该程序中的第一个声明声明了两个普通的整数变量 i 和 j。行 int *p 声明了一个名为 p 的指针。这行代码要求编译器声明一个指向整数的指针变量 p。星号(*)表示正在声明一个指针,而不是普通变量。你可以创建指向任何类型数据的指针:浮点数、结构体、字符等等。只需使用星号(*)来表示你想要一个指针而不是普通变量。
行 p = &i; 对你来说肯定是新的。在C语言中,& 称为地址运算符。表达式 &i 意为“变量 i 的内存地址”。因此,表达式 p = &i; 意为“将 i 的地址赋给 p”。一旦执行此语句,p 就“指向”了 i。在此之前,p 包含一个随机的、未知的地址,使用它很可能会导致分段错误或类似的程序崩溃。
可视化正在发生的事情的一个好方法是画一张图。在声明 i、j 和 p 之后,世界看起来就像上面的图片。
在这张图中,变量 i、j 和 p 都已声明,但均未初始化。因此,这两个整数变量被绘制成带有问号的方框——在程序执行的这一点上,它们可能包含任何值。指针被绘制成一个圆圈,以区别于保存值的普通变量,随机箭头表示它此刻可以指向任何位置。
在执行行 p = &I; 之后,p 被初始化并指向 i,如下所示
一旦 p 指向 i,内存位置 i 就有了两个名称。它仍然被称为 i,但现在也称为 *p。这就是C语言如何谈论指针变量的两个部分:p 是保存地址的位置,而 *p 是该地址所指向的位置。因此,*p=5 意味着 p 所指向的位置应设置为 5,如下所示
因为位置 *p 也是 i,所以 i 也取值 5。因此,j=i; 将 j 设置为 5,并且 printf 语句输出 5 5 5。
指针的主要特点是它的两部分性质。指针本身保存一个地址。指针还指向一个特定类型的值——即指针所保存地址处的值。在这种情况下,指针本身是 p。被指向的值是 *p。