C语言中的声明--函数声明、指针函数、函数指针、typedef

时间:2021-10-29 08:34:38
   最近在看《程序员面试宝典》对于第6章指针和引用中的部分复杂一些的声明比较头痛,于是忍不住又翻了翻《C Primer Plus》第14章,做一下归纳:

   其实无外乎就是指针、数组、函数指针的各种组合。分析一个复杂些的声明和写一个复杂些的声明是一个正向和逆向的推导过程。
   分析一个声明,先要分层,先确定这个声明是个函数指针、指针、数组,再一层一层的剥开分析。
   而写一个声明,由于有文字描述(面试题),或者有清晰的需求,反而刚开始就一定定义好要声明的属性,是一个函数指针、指针、数组。

最后:
一定要记得C中的修饰符的意义和结合优先级–实在觉得记不住,多写几个括号也行。
*
表示一个指针
[]
表示一个数组
()
表示一个函数

结合优先级为()=[] > *

以上符号只在本文的是用范围内讨论,不涉及上述三个符号的其他用途。

float (**a)[10]

首先将**a看做一个整体T;
第一层定义是一个有10个元素的数组,数组里都是float类型的数据
第二层a是一个二级指针,该指针指向这个数组
a指向一个指针p,该指针指向q,q指向一个float example[10]的一维数组;

float *(*a)[10]

首先将*a看做一个整体T;
第一层定义这是一个指针的数组,数组长度为10,每个元素都是double *;
第二层T是一个指针,这个指针指向一个
“长度为10,每个元素都是一个double*”

double(*a[10])()

将*a[10]看做一个整体T;
第一层定义是一个函数,函数为double ,无输入参数;
第二层T,由于T是分符号优先级,[]的优先级大于*,
因此,这个T是一个数组,数组元素都是指针。 这些指针式指向第一层中的函数类型的。
因此a是一个函数指针组成的数组,该数组长度为10,数组元素都是指向double func()这
样函数的指针。

int*((*a)[10])

将(*a)[10]看做一个整体T,
第一层定义是一个指向int 类型的指针
第二层由于*a有括号,因此是一个指针,加上后面的[10],因此这是个指针的数组,数组长 
度为10。数组元素都是指针,这些指针(数组元素)都是指向第一层中(int *)的指针
另外:如果去掉最外面括号(按照优先级本来就可以去掉最外侧括号),同上面第二个解释

long (*a)()

a是一个函数指针,指向long f ();类型的函数

int (*(*a)(int,int))(int)

将(*(*a)(int,int))看做一个整体T:
第一层定义是一个函数,函数有一个int类型的返回值,一个int类型的输入值。
第二层首先判断这是个指针,这个指针必定是指向第一层的函数的,也就是((*a)
(int,int))整体是一个函数指针
第三层(*a)(int,int)是一个函数指针模样,因此a是一个函数指针,而该函数指针的返回
值类型是第二层中的指针,输入值是两个int类型。

int *a[10]:

由于[]的优先级高,因此后面a[10]表示一个数组,从左到右分析:
这是一个指针,分析a[10],这时一个数组,数组里是指针。

小结:
内层是指针,这个指针是指向外层类型
内层是数组,那这个数组的元素师外层类型
内层是函数的,这个函数的返回值是外层类型
——————————我是复杂的分割线—————————————
下面是描述,然后写出声明:
一个整型数:
a
一个指向整型数的指针
int *a
一个指向指针的指针,它指向的指针是一个指向一个整型数
int **a;
一个有10个整型数的数组
int a[10]
一个有10个指针的数组,该指针式指向一个整型数的
int *a[10]
定义是一个数组 一个指向有10个整型数数组的指针
int (*a)[10];
定义是一个指针一个指向函数的指针,该函数有一个整形 参数并返回一个整形数
int (*a)(int ,int);
一个有10个指针的数组,该指针指向一个有整形参数,返回一个整形数
int (*a[10])(int);
–最后这个函数指针的数组平时我以为用不到,但在翻看NXP提供的源代码里,这帮歪果仁特别喜欢在驱动中用这种函数指针数组,因为驱动的对外接口一般都是一样,什么init(),uinit(),io_write()等,于是这帮人各种这种声明,然后各种goto,果然驱动的代码是丑陋的啊!

typedef:把狼招来了

typedef是C提供的让用户可以为某一个类型创建自己名字。我们最常见的就是给结构体创建名字,然后就可以直接用新建的名字进行结构体创建,而省去关键字”struct”,或者”enum”。

下面我们首先看一下C Primer中对声明的花样玩法:(Page412)
int board[8][8]:
二维数组
int **ptr;
二级指针
int *risk[10]
优先级[]>*,从左到右,内层是数组,外层是指针
具有10个元素的数组
int (*risk)[10]:
外层是数组,内层是指针,
指向数组的指针
一个指针,指向具有10个元素的int数组
int * oof[3][4]
优先级[]>*,从左到右,内层是数组,外层是指针
一个3*4的数组,每个元素都是一个指向int的指针
int (*uuf)[3][4]
内层是指针,外层是数组,
指向数组的指针
int (*uof[3])[4]
第一层为数组 int TYPE_1 [4]
第二层为指针 *TYPE_2
第三层为数组
一个具有2个元素的数组,每个元素是一个指针,每个指针是指向具有4个元素的int数组的指针。
再说typdef招来的狼:
typedef int arry5[5]
arr5被定义成一个只有5个int元素的数组

typedef arr5 * p_arr5
定义p_arr5是指向arr5的指针,
typedef p_arr5 arrp10[10]
定义arrp10数组,数组中有10个元素,每个元素都是一个指向有5个int元素的数组
arr5 togs
p_arr5 p2
arrp10 ap;
——————————OVER——————————–