C语言中指针学习方法之优秀

简介: C语言中指针学习方法之优秀

第一:先来看一下指针数组、二维数组指针、函数指针等几种较为复杂的指针,它们的定义形式分别是:

  1. int *p1[6]; //指针数组
  2. int *(p2[6]); //指针数组,和上面的形式等价
  3. int (*p3)[6]; //二维数组指针
  4. int (*p4)(int, int); //函数指针

 相信大部分初学者对上面几种形式的指针都非常迷惑,不知道该从哪里入手去理解,为什么 p1、p2 是数组,而 p3 却是指针呢,它们仅仅是一个括号的区别。


第二:指针是C语言中最强大最灵活的一部分,也是最难以理解的一部分,它是学习C语言的重点,没有学会指针就无从谈学会C语言。如果大家觉得上面几种形式的指针还能勉强接受,那么下面两个指针是不是让人抓狂呢?

  1. char *(* c[10])(int **p);
  2. int (*(*(*pfunc)(int *))[5])(int *);


第三:只要找到了窍门,再复杂的指针也是可以理解的,这节我们就来戳破这层窗户纸!


C语言标准规定,对于一个符号的定义,编译器总是从它的名字开始读取,然后按照优先级顺序依次解析。对,从名字开始,不是从开头也不是从末尾,这是理解复杂指针的关键!


对于初学者,有几种运算符的优先级非常容易混淆,它们的优先级从高到低依次是:


第一:定义中被括号( )括起来的那部分。

第二:后缀操作符:括号( )表示这是一个函数,方括号[ ]表示这是一个数组。

第三:前缀操作符:星号*表示“指向xxx的指针”。

第四:学会了“绝杀招式”,接下来我们就由浅入深,逐个击破上面的指针定义。

1) int *p1[6];

从 p1 开始理解,它的左边是 *,右边是 [ ],[ ] 的优先级高于 *,所以编译器先解析p1[6],p1 首先是一个拥有 6 个元素的数组,然后再解析int *,它用来说明数组元素的类型。从整体上讲,p1 是一个拥有 6 个 int * 元素的数组,也即指针数组。

2) int (*p3)[6];

从 p3 开始理解,( ) 的优先级最高,编译器先解析(*p3),p3 首先是一个指针,剩下的int [6]是 p3 指向的数据的类型,它是一个拥有 6 个元素的一维数组。从整体上讲,p3 是一个指向拥有 6 个 int 元素数组的指针,也即二维数组指针。


为了能够通过指针来遍历数组元素,在定义数组指针时需要进行降维处理,例如三维数组指针实际指向的数据类型是二维数组,二维数组指针实际指向的数据类型是一维数组,一维数组指针实际指向的是一个基本类型;在表达式中,数组名也会进行同样的转换(下降一维)。

3) int (*p4)(int, int);

从 p4 开始理解,( ) 的优先级最高,编译器先解析(*p4),p4 首先是一个指针,它后边的 ( ) 说明 p4 指向的是一个函数,括号中的int, int是参数列表,开头的int用来说明函数的返回值类型。整体来看,p4 是一个指向原型为int func(int, int);的函数的指针

4) char *(* c[10])(int **p);

这个定义有两个名字,分别是 c 和 p,乍看起来 p 是指针变量的名字,不过很遗憾这是错误的。如果 p 是指针变量名,c[10]这种写法就又定义了一个新的名字,这让人匪夷所思。
以 c 作为变量的名字,先来看括号内部(绿色粗体):

char * (* c[10]) (int **p);

[ ] 的优先级高于 *,编译器先解析c[10],c 首先是一个数组,它前面的*表明每个数组元素都是一个指针,只是还不知道指向什么类型的数据。整体上来看,(* c[10])说明 c 是一个指针数组,只是指针指向的数据类型尚未确定。


跳出括号,根据优先级规则(() 的优先级高于 *)应该先看右边(红色粗体):

char * (* c[10]) (int **p);

( )说明是一个函数,int **p是函数参数。

再看左边(橘黄色粗体):

char * (* c[10]) (int **p);

char *是函数的返回值类型。

从整体上看,我们可以将定义分成两部分:

char * (* c[10]) (int **p);

绿色粗体表明 c 是一个指针数组,红色粗体表明指针指向的数据类型,合起来就是:c 是一个拥有 10 个元素的指针数组,每个指针指向一个原型为char *func(int **p);的函数。

5) int (*(*(*pfunc)(int *))[5])(int *);

从 pfunc 开始理解,先看括号内部(绿色粗体):

int (*(*(*pfunc)(int *))[5])(int *);

pfunc 是一个指针。

跳出括号,看它的两边(红色粗体):

int (*(*(*pfunc)(int *))[5])(int *);

根据优先级规则应该先看右边的(int *),它表明这是一个函数,int *是参数列表。再看左边的*,它表明函数的返回值是一个指针,只是指针指向的数据类型尚未确定。

将上面的两部分合成一个整体,如下面的蓝色粗体所示,它表明 pfunc 是一个指向函数的指针,现在函数的参数列表确定了,也知道返回值是一个指针了(只是不知道它指向什么类型的数据)。

int (* (*(*pfunc)(int *)) [5])(int *);

蓝色粗体以外的部分,就用来说明函数返回什么类型的指针。

我们接着分析,再向外跳一层括号(红色粗体):

int (* (*(*pfunc)(int *)) [5])(int *);

[ ] 的优先级高于 *,先看右边,[5] 表示这是一个数组,再看左边,* 表示数组的每个元素都是指针。也就是说,* [5] 是一个指针数组,函数返回的指针就指向这样一个数组。

那么,指针数组中的指针又指向什么类型的数据呢?再向外跳一层括号(橘黄色粗体):

int (* (*(*pfunc)(int *)) [5]) (int *);

先看橘黄色部分的右边,它是一个函数,再看左边,它是函数的返回值类型。也就是说,指针数组中的指针指向原型为int func(int *);的函数。


将上面的三部分合起来就是:pfunc 是一个函数指针(蓝色部分),该函数的返回值是一个指针,它指向一个指针数组(红色部分),指针数组中的指针指向原型为int func(int *);的函数(橘黄色部分)。


总结:指针在C语言中是非常灵活的,在使用指针的时候,一定要从名字开始分析核心。


目录
相关文章
|
18天前
|
安全 C语言
【C语言】如何规避野指针
【C语言】如何规避野指针
20 0
|
8天前
|
C语言
c语言指针总结
c语言指针总结
14 1
|
5天前
|
人工智能 测试技术 C语言
C语言学习
C语言学习
13 1
|
8天前
|
Shell Linux 编译器
C语言,Linux,静态库编写方法,makefile与shell脚本的关系。
总结:C语言在Linux上编写静态库时,通常会使用Makefile来管理编译和链接过程,以及Shell脚本来自动化构建任务。Makefile包含了编译规则和链接信息,而Shell脚本可以调用Makefile以及其他构建工具来构建项目。这种组合可以大大简化编译和构建过程,使代码更易于维护和分发。
27 5
|
9天前
|
Shell Linux 编译器
C语言,Linux,静态库编写方法,makefile与shell脚本的关系。
总结:C语言在Linux上编写静态库时,通常会使用Makefile来管理编译和链接过程,以及Shell脚本来自动化构建任务。Makefile包含了编译规则和链接信息,而Shell脚本可以调用Makefile以及其他构建工具来构建项目。这种组合可以大大简化编译和构建过程,使代码更易于维护和分发。
16 3
|
10天前
|
传感器 人工智能 物联网
【C 言专栏】C 语言与硬件交互的方法
【5月更文挑战第4天】C 语言在硬件交互中扮演关键角色,主要通过直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射I/O和设备驱动程序开发。挑战包括硬件多样性、实时性要求和错误处理。随着物联网和人工智能发展,C语言与硬件交互的需求增加,未来将面临更多新硬件和技术的挑战。本文旨在帮助读者理解和掌握这一领域的知识,以实现更高效的硬件互动。
【C 言专栏】C 语言与硬件交互的方法
|
14天前
|
算法 C语言
【C 言专栏】C 语言文件操作的技巧与方法
【4月更文挑战第30天】本文介绍了C语言文件操作的关键技巧,包括文件的打开与关闭(使用`fopen`和`fclose`函数),读取(`fgetc`、`fgets`和`fread`)和写入(`fputc`、`fputs`和`fwrite`)操作。此外,还讨论了文件指针移动(`fseek`)、错误处理、文件权限和格式等问题。文中提供了一个简单的读写文件的示例,并提到了高级技巧如随机访问、文件缓冲和截断。掌握这些技能将有助于提升C语言编程中的文件处理能力。
|
14天前
|
存储 程序员 C语言
【C 言专栏】C 语言指针的深度解析
【4月更文挑战第30天】C 语言中的指针是程序设计的关键,它如同一把钥匙,提供直接内存操作的途径。指针是存储其他变量地址的变量,通过声明如`int *ptr`来使用。它们在动态内存分配、函数参数传递及数组操作中发挥重要作用。然而,误用指针可能导致错误,如空指针引用和内存泄漏。理解指针的运算、与数组和函数的关系,以及在结构体中的应用,是成为熟练 C 语言程序员的必经之路。虽然挑战重重,但掌握指针将增强编程效率和灵活性。不断实践和学习,我们将驾驭指针,探索更广阔的编程世界。
|
15天前
|
算法 搜索推荐 程序员
C语言中的函数指针和回调函数
C语言中的函数指针和回调函数
10 2
|
18天前
|
存储 编译器 C语言
【C语言】初步解决指针疑惑
【C语言】初步解决指针疑惑
7 0