详解C语言指针函数、函数指针、函数指针数组「建议收藏」

详解C语言指针函数、函数指针、函数指针数组「建议收藏」在C语言中,指针是一个很重要但是又很容易弄错的概念,也可以说指针就是C语言的灵魂,所以说学好指针对于完全掌握C语言是一个必须的过程。而在指针中,指针函数、函数指针、指针函数数组、函数指针数组、指向函数指针数组的指针等等概念看着又绕又头疼。本问总结了一下以上一些概念以及用法,并给出例程深化理解。1.指针函数指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数…

大家好,又见面了,我是你们的朋友全栈君。

在C语言中,指针是一个很重要但是又很容易弄错的概念,也可以说指针就是C语言的灵魂,所以说学好指针对于完全掌握C语言是一个必须的过程。而在指针中,指针函数、函数指针、指针函数数组、函数指针数组、指向函数指针数组的指针等等概念看着又绕又头疼。本问总结了一下以上一些概念以及用法,并给出例程深化理解。

1. 指针函数

指针函数就是返回指针值的函数,本质是一个函数。所以指针函数等价于“返回值为指针的函数”。

声明形式:type *func (参数列表)

#include <iostream>
using namespace std;


int *GetNum(int x); //指针函数声明形式


void main(void)
{
    cout << "===============start================" << endl;
    int num;
    cout << "Please enter the number between 0 and 6: ";
    cin >> num;
    cout << "result is:" << *GetNum(num) << endl;    //输出返回地址块中的值
    system("pause");
}

int *GetNum(int x) {
    static int num[] = { 0,1,2,3,4,5,6 };
    return &num[x];  //返回一个地址
}

2. 函数指针

函数指针就是一个指向函数的指针。每个函数在编译时,会被分配一个入口地址,一般用函数名来表示,这个地址就是该函数的指针。

声明形式:type (*func)(参数列表 )

从上面的定义形式可以看出,函数指针和指针函数的直观上区别在于指针符号*与函数名/指针名有没有用括号()包裹起来,从这一点来看是很容易区分两者的。

#include <iostream>
using namespace std;

int max(int a, int b) {
    return a>b ? a : b;
}

void main(void)
{
    cout << "===========start===========" << endl;
    int(*func)(int, int);       //定义一个指向该函数形式的指针变量
    func = max;
    int a, b;
    cout << "Please enter two numbers:";
    cin >> a >> b;
    cout << "max=" << (*func)(a, b) << endl;    //运用指针变量调用函数
    cout << "max=" << max(a, b) << endl;        //使用原函数调用
    cout << "max=" << func(a, b) << endl;       //使用函数指针名调用,func = max
    system("pause");
}

上例给出了函数指针的两种最普遍的调用形式,一个是直接用定义的指针变量(* func)调用,一个是用指针名调用,后者看起来就像是将原函数使用了新名称去调用一样,可以看成函数的别名。再次强调一下:指针变量名和指针符号 * 一定要用括号包裹起来。函数指针还有一种常用的使用方式,就是使用typedef定义后再使用。将上例稍作修改如下:

#include <iostream>
using namespace std;

int max(int a, int b) {
    return a>b ? a : b;
}

typedef int(*func)(int, int);

void main(void)
{
    cout << "===========start===========" << endl;
    func maxfunc = max;
    int a, b;
    cout << "Please enter two numbers:";
    cin >> a >> b;
    cout << "max=" << (*maxfunc)(a, b) << endl; //运用指针变量调用函数
    cout << "max=" << max(a, b) << endl;        //使用原函数调用
    cout << "max=" << maxfunc(a, b) << endl;        //使用函数指针名调用,func = max
    system("pause");
}

3. 函数指针数组

顾名思义,就是每个元素都是函数指针的数组,直接在函数指针名后面加上数组符号[ ]即可。

声明形式:type (*func[ ])(参数列表 )

#include<iostream>
using namespace std;

void fun1()
{
    cout << "调用函数fun1" << endl;
}
void fun2()
{
    cout << "调用函数fun2" << endl;
}
void fun3()
{
    cout << "调用函数fun3" << endl;
}
int main()
{
    //定义三个函数指针
    void(*pfun)() = &fun1;
    void(*pfun2)() = &fun2;
    void(*pfun3)() = &fun3;
    //接下来就是定义一个数组把他们三个装进去。
    void(*pfunarr[3])();
    void(*pfunarr[3])();
    pfunarr[0] = pfun;
    pfunarr[1] = pfun2;
    pfunarr[2] = pfun3;
    /* 或者这样赋值 pfunarr[0] = &fun1; pfunarr[1] = &fun2; pfunarr[2] = &fun3; */
    //调用运行
    pfunarr[0]();
    pfunarr[1]();
    pfunarr[2]();
    /* 或者这样调用 (*pfunarr[0])(); (*pfunarr[1])(); (*pfunarr[2])(); */
    system("pause");
    return 0;
}

4. C语言函数不可以定义为数组,只能通过函数指针来操作定义函数指针数组。

5. 指向函数指针数组的指针

声明形式:type (* (*func )[ ])(参数列表 )

#include<iostream>
using namespace std;

void fun1()
{
    cout << "调用函数fun1" << endl;
}
void fun2()
{
    cout << "调用函数fun2" << endl;
}
void fun3()
{
    cout << "调用函数fun3" << endl;
}
int main()
{

    //void(*pfun)() = &fun1;
    //void(*pfun2)() = &fun2;
    //void(*pfun3)() = &fun3;
    //接下来就是定义一个数组把他们三个装进去。
    void(*pfunarr[3])();
    void(*(*pfunarr2)[3])();
    //在这里呢看着个指针数组,他就是一个具有3个以函数指针为内容的元素的函数指针数组。
    pfunarr[0] = &fun1;
    pfunarr[1] = &fun2;
    pfunarr[2] = &fun3;

    pfunarr2 = &pfunarr;
    (*pfunarr2)[0]();
    pfunarr[0]();
    system("pause");
    return 0;
}

分析其定义形式:void(*(*pfunarr2)[3])()
其中(* pfunarr2)[3]表示数组指针,而void(* )( )表示函数指针,两者结合起来就是指向函数指针数组的指针。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/152169.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • subline text 激活码(最新序列号破解)[通俗易懂]

    subline text 激活码(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月19日
  • Android ListView下拉/上拉刷新:设计原理与实现「建议收藏」

    Android ListView下拉/上拉刷新:设计原理与实现「建议收藏」《AndroidListView下拉/上拉刷新:设计原理与实现》Android上ListView的第三方开源的下拉刷新框架很多,应用场景很多很普遍,几乎成为现在APP的通用设计典范,甚至谷歌官方都索性在AndroidSDK层面支持下拉刷新,我之前写了一篇文章《AndroidSwipeRefreshLayout:谷歌官方SDK包中的下拉刷新》专门介绍过(链接地址:http://bl

    2022年7月22日
  • Python爬虫常用:谷歌浏览器驱动——Chromedriver 插件安装教程

    Python爬虫常用:谷歌浏览器驱动——Chromedriver 插件安装教程我们在做爬虫的时候经常要使用谷歌浏览器驱动,今天分享下这个Chromedriver插件的安装方法。第一步、打开谷歌浏览器打开设置面板第二步、查看当前谷歌浏览器版本号第三步、点击插件下载,进去这个界面,找到跟自己谷歌浏览器版本号最相近的那一个。下载地址:插件下载这里有许多的版本,注意icons/向下的版本是无用的。选择icons/以上的版本,越靠近icons/的版本越新。第四步、找到对应版本后点击它计进入这个页面,点击notes.txt查看与Chrome版本是否对应。第五步、回

    2022年5月11日
  • APP抓包——Fiddler工具

    APP抓包——Fiddler工具Fiddler简介:Fiddler是强大且好用的Web调试工具之一,它能记录客户端和服务器的http和https请求,允许你监视,设置断点,甚至修改输入输出数据。Fiddler的运行机制其实就是本机上监听8888端口的http代理。对于PC端Fiddler启动的时候默认IE的代理设为了127.0.0.1:8888,而其他浏览器是需要手动设置的,所以如果需要监听PC端Chrome网络请求,…

    2022年5月29日
  • 展示组件(Presentational component)和容器组件(Container component)之间有何不同

    展示组件(Presentational component)和容器组件(Container component)之间有何不同展示组件(Presentational component)和容器组件(Container component)之间有何不同

    2022年4月22日
  • Java面向对象的三大特征以及理解

    Java面向对象的三大特征以及理解Java面向对象的三大特征为:封装、继承和多态,本文说说我对三大特性的理解。1.封装Java中的封装是指一个类把自己内部的实现细节进行隐藏,只暴露对外的接口(setter和getter方法)。封装又分为属性的封装和方法的封装。把属性定义为私有的,它们通过setter和getter方法来对属性的值进行设定和获取。下面我举一个简单的封装例子publicclassPerson{priva…

    2022年7月25日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号