C:函数指针的坑

关于该死的函数指针和指针函数

先来个目录

常量指针、指针常量

数组指针、指针数组

函数指针、指针函数

1、先看第一组

int const *p;// 常量指针,读作:指向常量的指针

int *const p;// 指针常量,读作:是常量的指针

2、第二组

int (*p)[5];// 数组指针,读作:指向数组的指针

int *p[5];// 指针数组,读作:元素是指针的数组

3、最后一组

int (*fun)(void );// 函数指针,读作:指向函数的指针

int *fun(void );// 指针函数,读作:返回值是指针的函数


好了,看完上面的,是不是很想吐

我们就干脆恶心到底

一、仔细分析第一组,论类型,我们从前看int const *和int *const都是整形指针。再看变量,此时我们从变量名开始看,*p我们理解时是向p指向的内存取值,再加上const,就变成了我们用指针取值是常量,就是指向了常量。而const p则是p保存的内容为常量,即地址为常量,也就是这个指针是常量。

二、再看第二组,

首先我们要对指针(*)和数组([])这两个符号的优先级补充一下,关于地址操作的两个符号(*(解引用)&(取址))都是单目运算符,而[]操作是初等运算符,初等运算符的优先级是高于单目运算符的,所以我们常常定义的指针数组int *p[5]结合起来应该是int *(p[5])。

然后,我们还有一个在理解指针时的bug,int *p喜欢写成int* p,我们理解的理所当然:“定义指针,数据类型是int*而不是int“。再结合这里我们把int *(p[5])看成int* (p[5])

最后,其实在民间,数组可以这样理解,int p[5] -->int[5] p,是不是很JAVA。


总结上面三点的理解我们的int *p[5]变成了int* (p[5]),数据类型是大小为5个int*、命名为p的数组。

然后int (*p)[5]也就是 int[5]* p,数据类型是一个指向(数据类型是大小为5个int、没有命名的数组)的指针。

真的好恶心,,,想吐




在讲第三组前,乱入一个东西,巩固一下上面两组。

typedef

不用想太多,既然我在这里强调,一定是很恶心的

typedef int (*pT)[5];

int a[][5]={1,2,3,4,5,6,7,};

pT b = a;

printf("%d\n",b[1][0]);

是不是很惊悚,还有这种操作!。。。

我不多说了,脑补一下也就知道了它的作用




三、我们再回到正题,讲第三组

其实第三组从内容上,并没有什么太特殊的。

所以后面,,,我准备了点小惊喜: ).....

我们都知道,变量名前面加类型,表示这个变量返回的是什么类型的数据。例如:加指针,表示返回指针。

变量后加括号,表示这是一个函数名。

int (*fun)(void )这个样子确实不太好理解,我们知道指针和数组是有时可以互换的,我们变一下:int(fun[5])(void)。这样是不是好想多了,假定int A()是一个函数,那么我们把A换成a[5]就变成了五个用数组标号的函数。

那么,我们就可以把int (*fun)(void)中的fun理解成一个指针,一个指向(返回值是int、参数是void)函数的指针。只不过这里的函数是匿名的。

是不是看到这里恍然大悟,,,

然后我们也就很简单的理解

typedef int(*funT)(void);指的是定义了一个新的数据类型,就是上面的那种。。。。。。

放心吧,我还有更坑更恶心的

( * ( void ( * ) ( ) ) 0 ) ( );

是不是很意外很惊喜!!!

吃鸡。。。。。

我们说一下它的来源,出自

图片发自《C陷阱与缺陷》

我们先回忆一下之前的知识点,当我们使用

typedef int(*funT)(void);

funT myFun = &function1;

可以看到我们生命了一个函数指针,并且指向了function1函数

那么我们该怎么使用myFun呢

定义指针时,

int *p;

p = &a;

b = *p;

所以,我们使用时,也是

(*myFun)();

所以,回到(* (void(*)()) 0)()

我们先忽略(void(*)()),因为是个强制转换我们先看其他,还剩下(*0)(),这个好理解吧,我们本来是要取址,只不过这里的址为0。但是我们要知道,0是没有数据类型的,我们取址出来的是不能使用的,所以就有了上面强制转换的部分,是不是很快就发现不要那个void其实和(*0)()的数据类型是一样的。正是如此,我们就是需要这种类型的指针。

再补上我们书上作者留的后言

图片发自《C陷阱与缺陷》

最后补充一点:ANSI C允许我们将(*fp)()简写为fp(),所以上文有的地方为了方便理解就可能使用了生僻的用法。

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

推荐阅读更多精彩内容