C语言-解读复杂声明

0 前言

>>返回AUTOSAR系列文章目录<<

尝试理解以下声明:

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)声明函数,()里的都是函数形参,不是符号
  1. 声明有且只有一个标识符和一个数据类型符,如果出现多个标识符或者数据类型符,一定是函数形参,视为函数符()的一部分,不单独分析
  2. 用来指明运算顺序的括号()不是声明符号,要与函数符区分

2 排序符号

分解出的符号按以下方式编号:

  1. 找出声明中唯一的标识符,编号为1
  2. 从标识符开始,括号内,向右寻找声明符号,分别按顺序编号
  3. 在括号内,标识符右边的声明符号都编完了,就从标识符开始向左寻找声明符号,继续编号
  4. 括号内编完后,往上一级括号,以括号为中心,继续先向右后向左编号
  5. 将声明符号按顺序写下来,1号一定是标识符,n号一定是数据类型符

示例1:

  • 声明:int (*func[5])(int *p)
  • 分解:int (* func [5])(int *p)
  • 排序:func[5]*(int p)int

3 连接

排序后,n个声明符号有(n-1)个箭头,按照顺序解读各箭头。

  1. 第一个箭头反应声明的本质,共有三种可能:
  • 标识符指针符:声明了一个指针变量
  • 标识符数组符:声明了一个数组变量
  • 标识符函数符:声明了一个函数
  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];
  1. 分解:int (* daytab)[13]
  2. 排序:daytab*[13]int
  3. 连接:
    第1个箭头:daytab*:声明一个指针*daytab
    第2个箭头:*[13]:指针指向一个13元素数组
    第3个箭头:[13]int:数组元素是int型
  4. 综合:声明指针变量*daytab,指向一个int[13]型数组

int *daytab[13];
  1. 分解:int * daytab [13]
  2. 排序:daytab[13]*int
  3. 连接:
    第1个箭头:daytab[13]:声明一个数组daytab[13]
    第2个箭头:[13]*:数组每个元素都是指针
    第3个箭头:*int:指针指向int型数据
  4. 综合:声明数组daytab[13],每个元素都是int*型指针

void (*comp)();
  1. 分解:void ( * comp) ()
  2. 排序:comp*()void
  3. 连接:
    第1个箭头:comp*:声明指针*comp
    第2个箭头:*():指针指向函数
    第3个箭头:()void:函数没有返回值
  4. 综合:声明指针*comp,指向一个没有返回值的函数

void *comp();
  1. 分解:void * comp ()
  2. 排序:comp()*void
  3. 连接:
    第1个箭头:comp():声明函数comp()
    第2个箭头:()*:函数返回值是指针
    第3个箭头:*void:指针是万能指针
  4. 综合:声明函数comp(),返回值是万能指针void*

char (*(*x())[])();
  1. 分解:char ( * (* x ()) []) ()
  2. 排序:x()*[]*()char
  3. 连接:
    第1个箭头:x():声明函数x()
    第2个箭头:()*:函数返回值是指针
    第3个箭头:*[]:指针指向数组
    第4个箭头:[]*:数组元素是指针
    第5个箭头:*():指针指向函数
    第6个箭头:()char:函数返回值是char型数据
  4. 综合:声明函数x(),函数返回值是指针,返回的指针指向指针数组,指针数组每个元素都指向返回值char型函数

char (*(*x[3])())[5];
  1. 分解:char ( * (* x [3] ) ()) [5]
  2. 排序:x[3]*()*[5]char
  3. 连接:
    第1个箭头:x[3]:声明数组x[3]
    第2个箭头:[3]*:数组元素是指针
    第3个箭头:*():指针指向函数
    第4个箭头:()*:函数返回值是指针
    第5个箭头:*[5]:指针指向数组
    第6个箭头:[5]char:数组元素是char型数据
  4. 综合:声明数组x[3],元素是指针,指针指向函数,函数返回值是指向char[5]型数组的指针

int (*func)(int);
  1. 分解:int ( * func ) (int)
  2. 排序:func*(int)int
  3. 连接:
    第1个箭头:func*:声明指针*func
    第2个箭头:*(int):指针指向形参为int的函数
    第3个箭头:(int)int:函数返回值int
  4. 综合:声明指针*func,指针指向形参int型、返回值int型的函数

int (*func[5])(int *p);
  1. 分解:int ( * func [5] )(int *p)
  2. 排序:func[5]*(int *p)int
  3. 连接:
    第1个箭头:func[5]:声明数组func[5]
    第2个箭头:[5]*:数组元素是指针
    第3个箭头:*(int *p):指针指向函数,函数形参int*
    第4个箭头:(int *p)int:函数返回值是int
  4. 综合:声明数组func[5],元素是指针,指针指向形参int*、返回值int的函数

int *func(int *)[5];
  1. 分解:int * func (int *) [5]
  2. 排序:func(int*)[5]*int
  3. 连接:
    第1个箭头:func(int*):声明函数func(int*)int*是形参类型
    第2个箭头:(int*)[5]:函数返回值是数组
    第3个箭头:[5]*:数组元素是指针
    第4个箭头:*int:指针指向int
  4. 综合:声明函数func(int*),返回值是数组,数组元素为int*型指针

char *(*(*f(char *(*para)(char *)))[2])()
  1. 分解:char * (* (* f (char *(*para)(char *))) [2])()
  2. 排序:f(char *(*para)(char *))*[2]*()*char
  3. 连接:
    第1个箭头:f(char *(*para)(char *)):声明函数f(),函数的形参很复杂,需要另外分析
    第2个箭头:(char *(*para)(char *))*:函数返回值是指针
    第3个箭头:*[2]:指针指向数组
    第4个箭头:[2]*:数组元素是指针
    第5个箭头:*():指针指向函数
    第6个箭头:()*:函数返回值是指针
    第7个箭头:*char:指针指向char型数据
  4. 综合:声明函数f(),返回值是指向数组的指针,数组元素是指向函数的指针,函数返回值是char*型指针

>>返回AUTOSAR系列文章目录<<

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值