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

Posted 从善若水

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级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️⃣留给读者自测,这里就不再给出分析过程了。

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


以上是关于高级C手把手教你分解C语言中复杂的变量声明的主要内容,如果未能解决你的问题,请参考以下文章

手把手教你c语言队列实现代码,通俗易懂超详细!

手把手教你0基础C语言速通

手把手教你C语言五子棋的实现(双玩家对战)

手把手教你0基础C语言速通

C 代码是如何跑起来的

手把手教你深入理解c/c++中的指针