博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持!
博主链接
本人就职于国际知名终端厂商,负责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)(); | 步骤1 | next是一个… |
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️⃣留给读者自测,这里就不再给出分析过程了。
这是从善若水的博客,欢迎大家关注我!