5.12复杂声明(上)

这章的复杂声明我并没有想去深入的研究,暂时,只要能看懂,稍微用一些有用的部分即可.因为这个复杂声明实在是复杂的过分.而且对于可读性来说简直是破坏性的.有可能自己之后去看都不知道是什么意思.这个只等我之后需要提高的时候再来深入研究.
这个复杂声明实在是不好解释,我在这里还是摘网上的一些高人写的总结比较好.


在c言语的复杂类型声明中,我们用到3个修饰符:*、()、[]。含义如下:

  • 暗示声明一个指针
    () 暗示声明一个函数
    [] 暗示声明一个数组
    c语言允许我们一次使用多个上面所说明的修饰符来申明一个变量,这样我们可以构造出多种多样的类别来。
    大家先看下面的例子:
    int board[8][8]; //二维数组(一个8个元素的数组,元素内容还是数组)
    int *p; //指向指针的指针(一个指针,内容还是一个指针)
    int array[10]; //10个元素的数组,元素内容是指针。
    int (
    p)[10]; //一个指针,指向含有10个元素的数组。
    int oof[3][4]; //3个元素的数组,存放的内容是指针,指针分别指向4个元素的数组
    int (
    oof)[3][4]; //一个指针指向3
    4 的数组。

看到这里,可能有人会想,你在说些什么哦,怎么看不明白,没有关系,看完下面的3条法则,你在来看上面的内容就很清晰了。
1:离名字越近的修饰符优先级越高
2:[],()优先级比*高
3:用()括起来的表达式的优先级最高。

我用这些法则来解释上面提到的例子,请看
int *foo[3][4]

名字:foo

、[3] 离名字一样近,而[4]离的比他们远,所以、[3]的优先级比[4]高。(法则1)
而 [] 的优先级比*高 (法则2)
优先级关系如下:
[3] > * > [4]

所以int foo[3][4] 是一个3个元素的数组(第一个修饰符[3]),存放内容是指针(第二个修饰符号),指针分别指向4个元素的数组(第三个修饰符[4])

int (*foo)[3][4]
名字:foo
优先级关系如下:(括号括起来的表达式优先级最高)

  • [3] > [4]
    所以一个指针指向3*4 的数组。


先从最简单的开始,逐步加深:
int (func)(int p);
首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个
号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(
func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int类型的形参,返回值类型是int。
int (
func)(int p, int (f)(int));
func被一对括号包含,且左边有一个
号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int 和int ()(int)这样的形参,返回值为int类型。再来看一看func的形参int (f)(int),类似前面的解释,f也是一个函数指针,指向的函数具有int类型的形参,返回值为int。
int (func[5])(int p);
func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个
,说明func的元素是指针,要注意这里的
不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比高,func先跟[]结合,因此修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int类型的形参,返回值类型为int。
int (
(func)[5])(int p);
func被一个圆括号包含,左边又有一个
,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个
号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int形参,返回值为int类型的函数。
int (
(*func)(int p))[5];
func是一个函数指针,这类函数具有int
类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。
要注意有些复杂指针声明是非法的,例如:
int func(void) [5];
func是一个返回值为具有5个int元素的数组的函数。但c语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。
int func5;
func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。


一、“right-left”规则
看过《C专家编程》中的分析规则,用起来并不是很舒服,遂在网上寻找,发现还有一个著名的“right-left”规则。规则经翻译总结后如下:

“right-left”规则:

  1. 规则中符号
  • 读作 “指向...的指针”
    [] 读作 “...的数组”
    () 读作 “返回...的函数”
  1. 起始点
    找到声明中的标识符(Identifier),它就是你分析的起始点,读作:“$(Identifier)是...”;

  2. 右边
    看你的标识符右边
    a) 如果发现“()”,你将知道这是一个函数声明,这时你可以说“$(Identifier)是返回...的函数”;
    b) 如果发现“[]”,你将知道这是一个数组声明,这时你可以说“$(Identifier)是...的数组”;
    c) 继续向右,直到遇到右边声明结束或者遇到“)”,继续下面。

  3. 左边
    看你的标识符左边
    a) 如果碰到的不是我们在0.中定义的符号,则直接说出它;否则按照0.中定义的符号含义说出。继续向左,直到遇到左边声明结束或“(”。

  4. 重复2和3的步骤,直到声明分析完毕。

二、例子详解
我们从简单到复杂,循序渐进。
[Example 1] int *p[];

  1. 找到标识符:p,读作:“p是...”;
  2. 向右看:发现一“[]”,然后遇到右边声明结尾,读作:“p是...的数组”;
  3. 向左看:发现一“*”, 读作:“p是指向...的指针的数组”;
  4. 继续向左看:没有发现0.中定义的符号,则分析结束,读作:“p是指向int类型的指针的数组”。

[Example 2] int (func())();

  1. 找到标识符:func,读作:“func是...”;
  2. 向右看:发现一“()”,然后遇到“)”,读作:“func是返回...的函数”;
  3. 向左看:发现一“*”,然后遇到“(”,读作:“func是返回指向...的指针的函数”;
  4. 向右看:发现一“()”,然后右边声明结束,读作:“func是返回指向返回...的函数的指针的函数”;
  5. 向左看:发现一“*”,读作:“func是返回指向返回指向...的指针的函数的指针的函数”;
  6. 向左看:没有发现.中定义的符号,则分析结束,读作:“func是返回指向返回指向int类型的指针的函数的指针的函数”。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容