跳转到内容

C/指针

本页使用了标题或全文手工转换
维基教科书,自由的教学读本
< C

指针的定义

[编辑]
  • 指针为一种变量,存储的内容是存储器地址。
  • 指针的使用会因为目的类型不同而有些微的影响。

理解指针

[编辑]

指针是C语言中一个较难理解的概念,因为这个概念很接近底层。要想理解它,要从计算机底层开始。

计算机底层的存储

[编辑]

在计算机内部有很多的存储单元,每个存储单元都可以存放数据。这些存储单元就像一个个小盒子,每个盒子里只能存放一个数字。

于是你看着眼前堆放的一大堆盒子,如何找到某个特定的盒子里存放的数据呢?

我们可以把盒子整齐排成一排,按顺序编号。这样,我们只需要报出编号,就能顺利找到一个盒子。

你可以想象,在计算机的虚拟世界中,有一个很高的柱子,这个柱子有很多层,每层都是一个格子,每个格子存放一个数字。这些格子按顺序编号,每个格子都有唯一的编号,用这个编号就能找到对应的格子。

无论采用哪种比喻,本质上都是相同的。内存中有很多存储单元,按顺序编号,用编号定位。这个“编号”就是“内存地址”。这就是计算机内部的内存组织形式。

指针

[编辑]

所谓指针,无非是一类变量,这类变量存储的值是存储单元的地址,而不是通常的需要加工处理的数据(不过少数情况下也可能对指针进行运算)。你可以理解成:“指针”就是“”向一个存储单元的“针”。

指针的类型

[编辑]

指针的类型,其实就是指针指向的存储单元中的数据的类型。任何类型的数据,在计算机内部都不过是二进制形式的数字。存储单元可没有区分数据类型的能力。所以,为了方便使用、避免出错,C语言的设计者让指针拥有了类型,这样就可以用指针的类型来区分目标存储单元中的数据的类型。

不同类型的指针在使用时是有区别的。

现实中的计算机几乎全部是按字节编址的,也就是每个小盒子里都只能装一字节(8 个二进制位)的数据。而在 C/基本数据类型 中讲到,不同类型的数据会占用不同字节数的空间,如 int 占用 4 字节、long long 占用 8 字节。

当我们使用指针时,即操作指针指向的存储单元的值时,实际上会连同这个目标存储单元后面的几个单元一起操作,具体的单元数量取决于指针的类型。比如,操作 int 型的指针指向的存储单元,就会从目标地址开始,一同操作四个单元的数据;操作 long long 型的指针指向的存储单元,就会一口气操作 8 个单元的数据。

你可以理解成,我们认为这几个连续的存储单元中存放了某种类型的数据,于是我们定义了一个指针为这种类型,并让它指向这段存储单元的开头。这样,我们只需要操作这个指针,就可以很方便的操作这几个连续存储单元中存放的整个数据。


讲完了理论,接下来该看看实践了。

变量指针

[编辑]
  • 指针的声明:

 int *ptr;  /* 则  (int *) 为变量类型,prt 为变量名称 */

  • 获取存储器地址:在变量前面使用 '&' 字符。
  • 指向存储器地址:在变量前面使用 '*' 字符。
#include <stdio.h>
int main()
{
    int v = 5;
    int *ptr = &v;
    printf("%d\n", *ptr);
}

函数指针

[编辑]

函数其实也可以是指针。

#include <stdio.h>
typedef void (*MyDelegate)(int i );
MyDelegate test1( int i ) 
{
    printf("%d\n", i );
}
MyDelegate test2( int i ) 
{
    printf("%d\n", i+1 );
}

int mainint argc, char* argv[]
{
    MyDelegate function;
    function = (MyDelegate)test1;
    function( 21 );  /* 等同于调用 test1 */
    function = (MyDelegate)test2;
    function( 21 );  /* 等同于调用 test2 */
}