美文网首页C语言程序员
C:函数指针的坑

C:函数指针的坑

作者: 一瓶AD钙谢谢 | 来源:发表于2017-08-18 13:43 被阅读0次

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

先来个目录

常量指针、指针常量

数组指针、指针数组

函数指针、指针函数

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(),所以上文有的地方为了方便理解就可能使用了生僻的用法。

相关文章

  • C语言

    C 指针、指针变量、函数指针、指针函数、指针数组、数组指针、C 数组

  • C:函数指针的坑

    关于该死的函数指针和指针函数 先来个目录 常量指针、指针常量 数组指针、指针数组 函数指针、指针函数 1、先看第一...

  • 02-C语言的指针

    02-C语言的指针 目标 C语言指针释义 指针用法 指针与数组 指针与函数的参数 二级指针 函数指针 指针在C中很...

  • C语言基础及指针⑤动态内存分配

    接续上篇C语言基础及指针④函数指针 在上一篇我们了解C语言中的函数及函数指针 , 使用函数指针 , 模拟了网络请求...

  • C语言函数指针和指针函数

    C语言函数指针和指针函数 在学习C语言的过程中,“指针函数”和“函数指针”经常容易搞混了, 最简单的辨别方式就是看...

  • C++函数指针和Swift的函数对象

    C++函数指针和Swift的函数对象 在C++中学习函数指针式非常痛苦的事情,而在Swift里面学习函数指针则是非...

  • c++ 指针

    原文地址摘要:这篇文章详细介绍C/C++的函数指针,请先看以下几个主题:使用函数指针定义新的类型、使用函数指针作为...

  • C语言指针导学(4)——分清函数指针和指针函数(转载)

    C语言指针导学(4)——分清函数指针和指针函数 http://blog.csdn.net/porscheyin/a...

  • 智能指针

    指针的危害 指针未初始化 野指针 内存泄漏 参考阅读C/C++指针使用常见的坑 智能指针分类 本质:将指针封装为类...

  • C语言基础----函数

    C语言面向过程,按照顺序执行,如果想放在前面,可以添加头文件、 指针函数和函数指针 指针函数是指带指针的函数,即本...

网友评论

    本文标题:C:函数指针的坑

    本文链接:https://www.haomeiwen.com/subject/teharxtx.html