0 前言
尝试理解以下声明:
int (*daytab)[13];
int *daytab[13];
void (*comp)();
void *comp();
char (*(*x())[])();
char (*(*x[3])())[5];
int (*func)(int);
int (*func[5])(int *p);
int *func(int *)[5];
char *(*(*f(char *(*para)(char *)))[2])();
1 分解符号
任何一个C语言声明,都由5种声明符号组合而成。
| 符号名 | 示例 | 说明 |
|---|---|---|
| 标识符 | a1; var_name, ptr; f | 声明的对象,有且只有一个 |
| 数据类型符 | void; int; char; | 在声明中有且只有一个,在最左端 |
| 指针符 | * | 声明指针 |
| 数组符 | []; [5]; [n] | 声明数组,注意[n]里的是数组大小,不是标识符 |
| 函数符 | (); (void); (int); (char* p) | 声明函数,()里的都是函数形参,不是符号 |
- 声明有且只有一个标识符和一个数据类型符,如果出现多个标识符或者数据类型符,一定是函数形参,视为函数符
()的一部分,不单独分析 - 用来指明运算顺序的括号
()不是声明符号,要与函数符区分
2 排序符号
分解出的符号按以下方式编号:
- 找出声明中唯一的标识符,编号为1
- 从标识符开始,括号内,向右寻找声明符号,分别按顺序编号
- 在括号内,标识符右边的声明符号都编完了,就从标识符开始向左寻找声明符号,继续编号
- 括号内编完后,往上一级括号,以括号为中心,继续先向右后向左编号
- 将声明符号按顺序写下来,1号一定是标识符,n号一定是数据类型符
示例1:
- 声明:
int (*func[5])(int *p) - 分解:
int(*func[5])(int *p) - 排序:
func→[5]→*→(int p)→int
3 连接
排序后,n个声明符号有(n-1)个箭头,按照顺序解读各箭头。
- 第一个箭头反应声明的本质,共有三种可能:
标识符→指针符:声明了一个指针变量标识符→数组符:声明了一个数组变量标识符→函数符:声明了一个函数
- 后续每一个箭头,右侧符号都是对左侧符号的修饰,每一个左侧符号都由唯一的修饰需求
指针→...:指针指向...数组→...:数组元素为...函数→...:函数返回值为...
解读示例1:func→[5]→*→(int p)→int
第1个箭头:func→[5]:声明了一个数组func[5],有5个元素
第2个箭头:[5]→*:数组每个元素都是指针
第3个箭头:*→(int p):指针指向形参为int型的函数
第4个箭头:(int p)→int:函数的返回值是int型
综合:声明了一个数组func[5],数组包含五个指向函数的指针,函数形参int型,返回值int型
4 前言案例说明
int (*daytab)[13];
- 分解:
int(*daytab)[13] - 排序:
daytab→*→[13]→int - 连接:
第1个箭头:daytab→*:声明一个指针*daytab
第2个箭头:*→[13]:指针指向一个13元素数组
第3个箭头:[13]→int:数组元素是int型 - 综合:声明指针变量
*daytab,指向一个int[13]型数组
int *daytab[13];
- 分解:
int*daytab[13] - 排序:
daytab→[13]→*→int - 连接:
第1个箭头:daytab→[13]:声明一个数组daytab[13]
第2个箭头:[13]→*:数组每个元素都是指针
第3个箭头:*→int:指针指向int型数据 - 综合:声明数组
daytab[13],每个元素都是int*型指针
void (*comp)();
- 分解:
void(*comp)() - 排序:
comp→*→()→void - 连接:
第1个箭头:comp→*:声明指针*comp
第2个箭头:*→():指针指向函数
第3个箭头:()→void:函数没有返回值 - 综合:声明指针
*comp,指向一个没有返回值的函数
void *comp();
- 分解:
void*comp() - 排序:
comp→()→*→void - 连接:
第1个箭头:comp→():声明函数comp()
第2个箭头:()→*:函数返回值是指针
第3个箭头:*→void:指针是万能指针 - 综合:声明函数
comp(),返回值是万能指针void*
char (*(*x())[])();
- 分解:
char(*(*x())[])() - 排序:
x→()→*→[]→*→()→char - 连接:
第1个箭头:x→():声明函数x()
第2个箭头:()→*:函数返回值是指针
第3个箭头:*→[]:指针指向数组
第4个箭头:[]→*:数组元素是指针
第5个箭头:*→():指针指向函数
第6个箭头:()→char:函数返回值是char型数据 - 综合:声明函数
x(),函数返回值是指针,返回的指针指向指针数组,指针数组每个元素都指向返回值char型函数
char (*(*x[3])())[5];
- 分解:
char(*(*x[3])())[5] - 排序:
x→[3]→*→()→*→[5]→char - 连接:
第1个箭头:x→[3]:声明数组x[3]
第2个箭头:[3]→*:数组元素是指针
第3个箭头:*→():指针指向函数
第4个箭头:()→*:函数返回值是指针
第5个箭头:*→[5]:指针指向数组
第6个箭头:[5]→char:数组元素是char型数据 - 综合:声明数组
x[3],元素是指针,指针指向函数,函数返回值是指向char[5]型数组的指针
int (*func)(int);
- 分解:
int(*func)(int) - 排序:
func→*→(int)→int - 连接:
第1个箭头:func→*:声明指针*func
第2个箭头:*→(int):指针指向形参为int的函数
第3个箭头:(int)→int:函数返回值int型 - 综合:声明指针
*func,指针指向形参int型、返回值int型的函数
int (*func[5])(int *p);
- 分解:
int(*func[5])(int *p) - 排序:
func→[5]→*→(int *p)→int - 连接:
第1个箭头:func→[5]:声明数组func[5]
第2个箭头:[5]→*:数组元素是指针
第3个箭头:*→(int *p):指针指向函数,函数形参int*
第4个箭头:(int *p)→int:函数返回值是int - 综合:声明数组
func[5],元素是指针,指针指向形参int*、返回值int的函数
int *func(int *)[5];
- 分解:
int*func(int *)[5] - 排序:
func→(int*)→[5]→*→int - 连接:
第1个箭头:func→(int*):声明函数func(int*),int*是形参类型
第2个箭头:(int*)→[5]:函数返回值是数组
第3个箭头:[5]→*:数组元素是指针
第4个箭头:*→int:指针指向int型 - 综合:声明函数
func(int*),返回值是数组,数组元素为int*型指针
char *(*(*f(char *(*para)(char *)))[2])();
- 分解:
char*(*(*f(char *(*para)(char *)))[2])() - 排序:
f→(char *(*para)(char *))→*→[2]→*→()→*→char - 连接:
第1个箭头:f→(char *(*para)(char *)):声明函数f(),函数的形参很复杂,需要另外分析
第2个箭头:(char *(*para)(char *))→*:函数返回值是指针
第3个箭头:*→[2]:指针指向数组
第4个箭头:[2]→*:数组元素是指针
第5个箭头:*→():指针指向函数
第6个箭头:()→*:函数返回值是指针
第7个箭头:*→char:指针指向char型数据 - 综合:声明函数
f(),返回值是指向数组的指针,数组元素是指向函数的指针,函数返回值是char*型指针
3808

被折叠的 条评论
为什么被折叠?



