指针

指针重要吗

指针在C语言中占据着重要的地位,指针有效的取代了在低端语言(如汇编语言与机器代码)直接使用内存地址。指针又比较贴近硬件,编译器能够很容易的将指针翻译为机器代码,这使指针操作时的计算机负担较少,同时简化一些C语言编程任务,能够提高程序的运作速度。

正是由于比较贴近硬件,并且指针可以与C语言中的其他数据结构(如数组、链表、结构体、函数)进行结合,可以说是贯穿了整本C语言。使得对于初学计算机编程的人理解起来有些难度。本文将结合图像和示例对指针的知识进行整理汇总,记录指针的学习过程,让指针也变得简单起来。


指针的定义

指针(英语:Pointer)在百科中给出的定义是编程语言中的一类数据类型及其对象或变量,用来表示或存储一个存储器地址,这个地址的值直接指向(points to)存在该地址的对象的值。

从这个定义中可以得到以下信息,首先指针也是一种数据类型,就像我们前面学到的int,char,float,double等基础数据类型。同样的指针也可以像其他基础数据类型一样定义变量,不同的地方在于指针变量中保存的是一个存储器的地址。

(补充:程序中所有的数据都是存储在内存中的,内存被分成一个个的内存单元,每个内存单元又有一个地址。系统内存就像是带有门牌号的小房间,如果要使用某个房间,就需要得到房间的门牌号。而指针变量存储的就是门牌号,即也就是存储器地址)。

指针定义变量的方式如下:

1
2
3
4
5
6
int *a,b=5;
char *c,d='m';
float *f,g=6.0;
a = &b;
c = &d;
f = &g;
  • int *为整型指针数据类型,定义了一个存储整型变量存储地址的指针变量a
  • char *为字符型指针数据类型,定义了一个存储字符型变量存储地址的变量c
  • float *为单精度浮点型指针数据类型,定义了一个存储浮点型变量存储地址的变量f

指针变量的赋值

两个指针运算符:

  • 地址运算符&
    取内存中变量的地址,例如&b,值为整型变量b的内存地址。

  • 取值运算符* 获取指针变量所指向变量的值,例如a,值为5。(注意与int *中的\相区别)

    a = &b;代表取出整型变量b的地址赋值给a,图中简单表示为2000赋值给a,即a指向变量b,a中存储了变量b的内存地址2000。指针变量c和f的赋值也一样如图所示。

这里要区分两个容易混淆的概念:

  1. 指针的类型
    指针的类型是指针变量本身的类型,指针变量在内存中占据4个字节,存储32位的内存地址码。
  • 指针变量a的类型为int *
  • 指针变量c的类型为char *
  • 指针变量f的类型为float *
  1. 指针指向的类型
    指向的类型是当前指针存储的内存地址中所存储变量的类型。
  • a指向的类型为int
  • c指向的类型为char
  • f指向的类型为float

指针与一维数组

我们都知道数组名是代表数组首元素地址的符号常量,而指针变量又可以存储地址,所以数组不仅可以通过数组名+下标的方式访问,也可以通过指向它的指针变量来访问。

指向数组的指针变量

我们前面定义的指针变量都是指向一个基础数据类型的变量,指向数组的指针变量定义方式也类似。

1
2
int c[5];
int *p = c;
  • 表达式(p+1)或(c+1)都代表数组元素c[1],其中p+1和c+1都代表c[1]的地址&c[1]。

  • 数组名称c为常量,故任何对数组名称赋值的操作都是错误的。

  • C语言不会对地址操作做越界检查,故数组越界不会报错,这也是程序容易出错的地方。

1
2
int (*p)[5];
int *p[5];
  • 上面第一个定义方式为,首先计算(),*p代表p是一个指针变量,然后是[5],代表p指向一个大小为5的数组,最后int,代表p指向的是一个存储整型变量的数组。即定义数组指针p,指向一个存储5个整型元素的数组。
  • [5]的优先级要高于*,故p首先是一个大小为5的数组,其存储的数据类型为指针变量,而指针指向的数据类型为整型int。

指针与二维数组

定义二维整型数组如下

1
int a[3][3] = {{14,16,19},{22,55,88},{33,54,32}};

二维数组a的元素是按行进行存储的,可以将a数组的3行看成3个分数组:a[0],a[1],a[2]。每个分数组是含3个列元素的一维数组。
如下图所示:

数组名a是指向0号分数组的指针常量,值为2000,同样不能够给a赋值。a+0,a+1,a+2则分别表示0号分数组,1号分数组,2号分数组,对应存储器地址值为2000,2004,2008。
其中a[0],a[1],a[2]为三个一维分数组的数组名称,这三个数组名存储的地址又分别指向a[0][0],a[1][0],a[2][0],对应的数值为3000,3006,3012。
a[0]+1和a[0]+2则是分别指向a[0][1],a[0][2]的指针常量,对应的地址值为3002,3004。

虽然a与a[0]的地址都是2000,但是并不等价,a的基类型字节数为4,a[0]为2,也可以从a+1与a[0]+1的不同结果看出。
以下是二维数组不同表示形式的含义与内容:

------ 本文结束------
  • 文章标题: 指针
  • 本文作者: 你是我的阳光
  • 发布时间: 2020年03月10日 - 15:59:04
  • 最后更新: 2021年08月03日 - 16:24:02
  • 本文链接: https://szp2016.github.io/c/指针/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
0%