理解复杂的c变量声明

1.前言
对于一些复杂的c语言变量声明,往往难以理解。
简单的,如:

int foo[5] ; //foo is an array of 5 ints
char *foo;   //foo is a pointer to char
double foo(); //foo is a function returning double

非常容易理解。稍微复杂的声明:

char *p[5] ;//p is a array of pointer to char
char (*p)[5]; //p is a pointer to array of char

理解起来有一定难度,对于极其复杂的:

char *(*(**foo[][8])())[];// what's the fuck?

理解起来相当有难度。
本文阐述一个理解此类复杂变量声明的简单且有效的方法。
2.基本类型与派生类型
除开变量名以外,一个完整的变量声明包含一个基本类型声明和零或者多个派生类型声明。理解这一点非常重要。
基本类型主要如下:

charsigned charunsigned charshortunsigned shortintunsigned intlongunsigned longfloatdoublevoidstruct tag   
• union tag   
• enum tag   

• long longunsigned long longlong double

一个变量声明中只有一个基本类型声明,且该类型声明往往位于声明表达式的最左边。

派生类型
c语言中有如下三种派生类型
* pointer to … 即指向…的指针
[] array of … 即包含…的数组
() function returning … 即返回…的函数
这种函数类型一般由一对封闭的括号组成,括号中间也有可能有指明函数参数类型的参数列表,但是在理解变量声明时我们可以忽略中间的参数列表。

3.理解规则
c语言中()、[]的优先级高于*,因此我们利用派生类型的英文含义来理解变量声明,可以以下规则:
(1)以变量的名字开始:
foo is …
(2)结束于变量的基本类型:
foo is … int
(3)中间的省略号部分,则是最关键的地方,其规则如下:“尽可能的向右读取派生类型,直到必须返回左边,则从左边最右侧开始”
即:从一个变量的名字开始,尽量向右边读取派生类型符号,直到碰到了右括号,此时向左找到这个括号匹配的左括号,并从该括号内尚未读取的字符的最右侧开始重复。

例子:
对于声明:

long **foo[7];

以变量名开始,以基本类型结束:
foo is … long
从foo开始向右读取第一个派生类型[]
foo is array of 7 … long
因为已经到头了,所以读取最右边*
foo is array of 7 pointer to … long
读取从右边开始,第二个*
foo is array of 7 pointer to pointer to long

由此,我们完整理解了该变量类型为:
foo 是一个大小为7的数组,其元素为指向long型的二重指针。

挑战终极难度:

char *(*(**foo[][8])())[];

首先:
foo is …char
向右第一个数组符号:
foo is array of …char
向右第二个数组符号:
foo is array of array of 8 … char
碰到右括号了,从括号内,距离foo最近的第一个*开始
foo is array of array of 8 pointer to …char
还在括号内,读取第二个*
foo is array of array of 8 pointer to pointer to… char
出第一个括号,继续向右,读取一个函数符()
foo is array of array of 8 pointer to pointer to function returning …char
碰到了右括号,返回左边,并从左边的最右开始(有点拗口,即从括号内左侧尚未读取的类型字符里最靠右的开始)
foo is array of array of 8 pointer to pointer to function returning pointer to …char
出了第二层括号,向右读取数组类型[]
foo is array of array of 8 pointer to pointer to function returning pointer to array of …char
到了最右,返回左侧
foo is array of array of 8 pointer to pointer to function returning pointer to array of pointer to char.
到此,大功告成!
翻译过来就是:foo是一个二维数组,这个数组的元素是
二级函数指针,函数返回类型为指向元素类型为char*的数组的指针,函数参数列表为空。
实际中,用这种类型的变量就是作死!

4.总结
本文将c语言变量声明表达式分为基本类型,和派生类型两部分,其中派生类型
在解析时分别对应
* pointer to…
[] array of…
() function returning…
解析时,从变量名开始,结束于基本类型,中间按照“尽可能的向右读取,直到必须返回左边,则从左边最右侧开始”的原则,来理解变量声明,最后可以翻译为对应的中文。

参考资料
Reading C type declarations

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值