【高级C】手把手教你分解C语言中复杂的变量声明

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接

本人就职于国际知名终端厂商,负责modem芯片研发。
在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G算力网络技术标准研究。


博客内容主要围绕:
       5G协议讲解
       算力网络讲解(云计算,边缘计算,端计算)
       高级C语言讲解
       Rust语言讲解

解析C语言中复杂的变量声明

这里给出几个例子,如果您能看懂就没必要看下文了,如果您有疑惑请继续看下面的解析:

例1️⃣

//next 是一个指针,它指向一个函数。这个函数没有入参,返回一个指向(chart * const)的指针。
//chart * const 表示这是一个常量指针,指向的数据是char类型

char * const *(*next)();

例2️⃣

//signal 是一个函数,它的入参是int类型的值以及一个函数指针,它返回一个函数指针
//入参和返回值中的函数指针类型相同(都是void (*)(int)),表示一个入参为int,返回值为void的函数

void (*signal(int,void (*)(int)))(int);

例3️⃣

//c是一个包含10个元素的数组,每个元素中存储的是一个指向函数的指针。
//这个函数入参是指向int型数值的二级指针,返回值是一个指向char型数值的一级指针

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

C语言解析变量声明的优先级规则

第一步:找到变量声明中的变量名;

第二步:按照下面的优先级进行分解(优先级从高到低)
              ① 包含变量名的圆括号中的内容优先进行分解;
              ②看右边,如果是 “()”则表示函数,如果是“[ ]”则表示数组;
              ③再看左边,如果是 “ * ”则表示指针;

第三步:如果 const、restrict、volatile 紧挨着类型标识符(e.g. int,long,etc),那么const、restrict、volatile 就是修饰类型标识符的。否则就是修饰它左边的指针。

上面说的比较抽象,我们使用开篇的一个例子进行解释,例3️⃣:

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

第一步:找到变量声明中的变量名,也就是变量名 “c”;

第二步:
            ① 包含变量名的圆括号中的内容优先进行分解,也就是我们先解析“char * (*c[10]) (int **p);” 这一部分;
            ② 看右边,如果是 “()”则表示函数,如果是“[ ]”则表示数组,我们看到右边是“[ ]”,则表明是一个数组,包含了10个元素
            ③ 再看左边,如果是 “ * ”则表示指针,左边是 “ * ”表示 数组中存放的是一个指针类型的数据

第三步:我们最后分析声明的剩余部分“ char * (*c[10]) (int **p); ”
            ① 看右边,如果是 “()”则表示函数,如果是“ [ ] ”则表示数组,我们看到右边是“()”,则表明是一个函数,这个函数的入参是 “ int ** ”类型的值,返回值是 “ char * ” 类型的值;

最后串联在一起就是:

//c是一个包含10个元素的数组,每个元素中存储的是一个指向函数的指针。
//这个函数入参是指向int型数值的二级指针,返回值是一个指向char型数值的一级指针

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

我们再看开篇的 例1️⃣:

char * const *(*next)();

第一步:找到变量声明中的变量名,也就是变量名 “next”;

第二步:
            ① 包含变量名的圆括号中的内容优先进行分解,也就是我们先解析“ char * const * (*next) (); ” 这一部分;
            ② 看右边,发现没有“ ( )”,也没有 “[ ]”;
            ③ 再看左边,如果是 “ * ”则表示指针,左边是 “ * ”表示 next是一个指针

第三步:我们最后分析声明的剩余部分“ char * const * (*next) (); ”
            ① 看右边,如果是 “()”则表示函数,如果是“ [ ] ”则表示数组。我们看到右边是“()”,则表明是一个函数,这个函数没有入参,返回值是 “ char * const * ” 类型的值;
            ② const 修饰的是谁?根据上面的 优先级规则—第三步,如果 const 紧邻 char 的左边或右边,则修饰的就是 char;否则修饰的就是紧挨在 const 左边的 “ * ”( char * const * )。
第四步:我们目前已经分析到这里了 char * const * (*next)(); ,此时我们需要从右往左看(因为右边已经没有东西了)。此函数的返回值是一个指针,这个指针指向一个 “ char * const ” 类型的数据。同理,const修饰的是 “ * ”,指向的这个数据是一个 由常量指针指向的数据类型是char的地址。


C语言变量声明解析万能图

请添加图片描述
这里给出一个例子:

char * const *(*next)();
剩余部分下一步结果
char * const *(*next)();步骤1next是一个…
char * const *(*        )();步骤2,3没有匹配项,继续下一步
char * const *(*        )();步骤4没有匹配项,继续下一步
char * const *(*        )();步骤5匹配到 “ * ”,解析为:是一个指针,指向一个…
跳回步骤4
char * const *(         )();步骤4继续步骤2
char * const *           ();步骤2没有匹配项,继续下一步
char * const *           ();步骤3解析为:是一个函数,返回一个…
char * const *             ;步骤4没有匹配项,继续下一步
char * const *             ;步骤5解析为:是一个指针,指向一个…
char * const               ;步骤5解析为:一个只读
char *                         ;步骤5解析为:一个指针
char                           ;步骤6解析为:char类型

开篇的例3️⃣留给读者自测,这里就不再给出分析过程了。

这是从善若水的博客,欢迎大家关注我!


在这里插入图片描述

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从善若水

原创不易,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值