内容简介
本文主要讲解C语言中,指针的应用及注意事项。
前言
话说平时编程用得最多的就是C语言,但对C语言掌握得还是不够熟练,尤其是指针这块。对于初学者来说,光听到这些名词,估计就已经晕了,比如指针的指针、指针函数、函数指针。接下来我将围绕这几个名词,展开一下讲解,首先从指针开始。
指针
何谓指针?指针即地址,表示的是一个变量的地址。如以下代码:1
2int a = 1;
int *b = &a;
定义了一个指针变量b,并用变量a的地址予以初始化。指针的初始化是使用&操作符完成的,它用于产生操作数的内存地址。这里b是一个指向整型变量的指针,对它解引用操作将产生一个整型值。
那什么是解引用操作?1
*b = 10 - *b;
*操作符执行的就是解引用操作,也叫间接访问或间接寻址操作。假设变量a的内存地址为0x100,这里对b使用间接访问操作,它表示访问内存位置0x100,并查看那里的值。以上语句包含了两个间接访问操作。右边的间接访问作为右值使用,它的值是b所指向的位置所存储的值(a的值)。左边的间接访问作为左值使用,所以b所指向的位置0x100(a)把赋值符右侧的表达式的计算结果作为它的新值。最终a的值变为9。
接下来看一道练习题,加深一下理解。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27int a,b;
void swap(&a,&b)交换a,b的值,swap的正确实现是( )
A.
void swap(int *p1,int *p2)
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
B.
void swap(int *p1,int *p2)
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
C.
void swap(int *p1,int *p2)
{
int *p;
p = p1;
p1 = p2;
p2 = p;
}
如果你能将上面每个选项分析清楚,那指针的基本概念应该就很清楚了。接下来我将一个一个分析。
三个选项的函数声明都一样,均包含了两个指针变量参数。A选项中,首先定义一个变量,然后对p1进行间接访问操作,而p1指向的位置存储的是变量a,因此p=1,之后又是间接访问操作,可参照前面讲解的解引用操作的例子。此时原先p1指向的位置存储的变量a的值等于p2指向的位置存储的b的值,即a=2。然后是赋值操作,b=1。这样即完成了a,b值的交换。
然后来看B选项,首先声明了一个名为p的指针变量,然后将p1指向的位置存储的变量a存储在p所指向的内存位置,后续操作同A,完成了a,b值的交换,看起来似乎没有问题。而实际上,当你将以上代码在macOS下跑一下,会报“Segmentation fault: 11”,即存储器段错误。它的意思是说无法访问非法的地址。好了,我们来仔细看看代码,一开始声明了一个指针变量p,但并未对其初始化。当执行下一条赋值操作时,会发生什么情况呢?一种情况是p的初始值是一个非法地址,于是出现刚刚的报错。另一种更坏的情况是,p的值可能为一个合法地址。接下来p对应地址的值被无意修改。因此对指针进行解引用操作之前,必须非常小心,确保其已被初始化。
最后看C选项,声明了指针变量p并使用变量a的地址进行了初始化,然后将变量b的地址赋值给p1,最后将变量a的地址赋值给p2。但至始至终,变量a、b的值都没有改变过。
指针的指针
……
函数指针
……
指针函数
……