c专题之指针---函数指针与指针函数与的区别用法

原创
2019/12/05 01:24
阅读数 0

----在写文章之前,我想把下午和网友一起讨论的问题拿出来分享一下(这里也感谢网友的问题讨论和解答)。下面是网友的讨论过程:


下面可以按照这位网友来解释上面的问题:


后面又遇到malloc这个函数的讨论问题,一开始我的解答是错误:


下面这位网友解释的比较好:


然后后面有一位网友对结构体的看法,我觉得非常有道理:


下面我们先来看最后一位网友的解释,怎么觉得他有道理呢,于是乎我自己用代码测试了一下,发现在定义结构体时,你在结构体里面没有放任何数据类型的定义,这个时候结构体不占用内存大小的(为啥会出现这种情况,我的理解是结构体类型是我们人为定义的一种(符合计算机的)数据类型),一般书上会叫复合类型,看书看的最多是这个叫法(那是因为后面结构体里面定义的各种数据类型的变量,甚至函数定义,所以这个结构体就像一个“黑洞”一样,当有数据类型被吸去,后面就可以一直吸东西,但是这个“黑洞”大小不能超过计算机所规定的内存大小的,这里纯属是个人的理解,如有理解不切当的地方,可以批评指出,非常欢迎您的批评意见);下面我们来看来代码来说话(其实下面我也写了空数组,就是在定义的时候,没有初始化数组元素大小,但是数组还是占用内存空间大小的,这是因为在数组类型定义的时候,计算机已经给它分配的内存大小):


同时在这过程还发现结构体字节对齐的问题(这个后面我也会专门写文章分享的,这里可以先看一下试验过程和结果):


好了,在这里非常感谢网友的讨论,自己也加深了对这一块的理解,如果我在上面理解有错误的地方,可以指出来。


一、指针函数和函数指针的区别:


1、其实在说这个的区别时,我前面讲数组指针和指针数组的时候,已经说出了理解方法来去理解这个区别(而不用去死记硬背,过了一段时间没有用,就会忘记了。):


    我们在定义一个符号时,关键在于:首先要搞清楚你定义的符号是谁:



          第一步:找核心(也就是谁是这个表达式里面的主体(变量))。



             第二步:找结合:

                           看谁跟核心最近、谁跟核心结合。如果核心和*结合,表示核心是指针;如果核心和[]结合,表示核心是数组;如果核心和()结合,表示核心是函数。



             第三步:以后继续向外扩展,不过这里要注意符号的优先级问题就可以更加好理解了。


2、用示例来举例说明:


     a、指针函数,:

              

1int *fun(int x);

这里的话因为运算符()的优先级比*的高,所以先确定是函数为核心,然后向外找,找到一个int *fun类型的指针,所以就叫指针函数了,下面是应用:

 1#include <stdio.h>
2 #include <stdlib.h>
3
4typedef struct Data{
5    int a;
6   int b;
7
8
9
10}Date;//这里的意思是把结构体类型重新命名成Date
11//指针函数
12Date * fun(int a,int b)
13 
{
14Date* date =(Date *)malloc(sizeof(Date)) ;
15date->a=a;
16date->b=b;
17return date;
18
19   } 
20     int main(void){
21
22  Date *myDate=fun(2,3);
23  printf("myDate->a=%d,myDate->b=%d\n",myDate->a,myDate->b);
24
25  return 0;
26
27
28}

输出结果:




    b、函数指针:

   

1int (*fun)(int x);

这里的话可以这样理解,因为指针fun又加了运算符(),所以(*fun)的优先级比单个的()的优先级高,所先确定指针为核心,然后向外找,找到函数形式(),所以这个式子就叫函数指针了。下面是应用:

 1#include <stdio.h>
2#include <stdlib.h>
3
4int add(int x,int y)
5{
6return (x+y);
7
8}
9int sub(int a,int b)
10{
11return (a-b);
12}
13//函数指针 
14int (*fun)(int x,int y);
15
16int main(void)
17 {
18fun=add;
19printf("the (*fun)(2,3)is %d\n)",(*fun)(2,3));
20//另外一种写法:
21fun=&sub;
22
23printf("the (*fun)(7,3)is %d\n)",(*fun)(7,3));
24
25return 0;
26 } 

输出结果:



3、要明白函数名其实是一个地址:

       a、函数的实质是一段代码,这一段代码在内存中是连续分布的(一个函数的大括号括起来的所有语句将来编译出来生成的可执行程序是连续的),所以对于函数来说很关键的就是函数中的第一句代码的地址,这个地址就是所谓的函数地址,在C语言中用函数名这个符号来表示,我们来试验代码测试:


二、总结:


      还是那句话,最好检验自己疑惑的方法,我觉得是自己有想法去写一个代码去测试,然后观察现象,并分析出结果,这样对自己非常有好处的。


---欢迎关注公众号,可以查看往期的文章,可以得到三本经典的c语言进阶电子书


Linux爱好者(对文章中写有不对的地方,可以批评指出,虚心向您学习,大家一起进步。加个人微信,可以进群交流有关Linux的技术等话题,群里只能讨论技术,发广告,立刻飞机):


本文分享自微信公众号 - TXP嵌入式(txp1121518wo-)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部