Skip to main content

C 指针进阶

1. 各种指针

  • 指针数组:每个数组元素里面都会存放一个指针变量。
  • 数组指针:指向数组的指针。
  • 指针函数:函数的返回值是一个指针变量。
  • 函数指针:指向函数的指针。
  • 结构体指针:指向结构体的指针。
  • ...

2. 指针万能拆解法

  • 任意的指针,不管有多复杂,其定义都有两部分组成。
    • 指针所指向的数据类型
    • 指针的名字
char (*p1); 				// 第2部分:*p1; 第1部分:char
char *(*p2); // 第2部分:*p2; 第1部分:char *
char **(*p3); // 第2部分:*p3; 第1部分:char **
char (*p4)[3]; // 第2部分:*p4; 第1部分:char [3]
char (*p5)(int, float); // 第2部分:*p5; 第1部分:char (int, float)
  • p1、p2、p3、p4、p5本质上并无区别,它们均是指针。
  • p1、p2、p3、p4、p5唯一的不同,是它们所指向的数据类型不同。
  • 第1部分的声明语句,如果由多个单词组成,C语言规定需要将其拆散写到第2部分的两边。

3. 指针数组和指针函数的拆解

int *p1[5];    // 第1部分:p1[5]; 第2部分:int *;
int *p2(void); // 第1部分:p2(void); 第2部分:int *;
  • 指针数组:我们可以从符号优先级去判断,因为数组下标 [ ] 的优先级是要比 ***** 的优先级高的,所以 p1 会先被定义成具有5个元素的数组,然后它的数据类型会是 **int ***。
  • 指针函数:我们可以从符号优先级去判断,因为小括号的优先级是要比 ***** 的优先级高的,所以 p2 会先被定义成一个函数,然后它的数据类型会是 *int ,然后函数的类型实际上就是函数的返回值,所以这个函数的返回值会是一个指针变量

注意:永远不要返回一个局部的指针变量。

4. 眼花缭乱的指针示例

int a = 100;									// int型变量
int *p = &a; // int型指针(指向int的指针)
int **pp = &p; // int型指针的指针

int arr[3] = {1, 2, 3, 4, 5}; // int型数组
int (*arrp)[3] = &arr; // 指向"int型数组"的指针
int *parr[3] = {&arr[0], &arr[1], &arr[2]}; // int型指针数组
int *(*parra)[3] = &parr[3]; // 指向"int型指针数组的指针"
int **pparr[3]; // int型指针的指针数组

int f(void) // 返回值为int的函数
int *pf(void) // 返回值为"int型指针"的函数
int **ppf(void) // 返回值为"int型指针的指针"的函数

int (*fp)(void) = &f; // 返回值为int的函数指针
int *(*pfp)(void) = &pf; // 返回值为int型指针的函数指针
int **(*ppfp)(void) = &ppf; // 返回值为int型指针的指针的函数指针

int (*fparr[3])(void) = {f, f, f}; // 返回值为int的函数指针的数组
int *(*pfparr[3])(void) = {pf, pf, pf}; // 指向"返回值为int型指针的函数"的指针的数组
int **(*ppfparr[3])(void) = {ppf, ppf, ppf}; // 指向"返回值为int型指针的指针的函数"的指针的数组

typedef int (*FP)(void);
FP fpf(void);
int (*fPf(void))(void); // 返回值为"返回值为int的函数指针"的函数
int (**fppf(void))(void); // 返回值为"返回值为int的函数的指针的指针"的函数
int *(*pfpf(void))(void); // 返回值为"返回值为int型指针的函数指针"的函数
int (*(*fpfp)(void))(void); // 返回值为"返回值为int的函数指针"的函数指针
int (**(*fppfp)(void))(void); // 返回值为"返回值为int的函数指针的指针"的函数指针
int *(*(*pfpfp)(void))(void); // 返回值为"返回值为int型指针的函数指针"的函数指针

int (*(*arrfp)(void))[3]; // 返回值为"指向int型数组"的函数指针
int *(*farrfp)(void)[3]; // 返回值为"int型指针数组"的函数指针
int *(*(*parrpfp)(void))[3]; // 返回值为"指向int型指针数组的指针"的函数指针
int (*(*(*(*pfparrpfp)(void))[3]))(void); // 返回值为"指向'返回值为int型指针的函数指针'的数组的指针"的函数指针