0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【C语言进阶】C语言指针的高阶用法

嵌入式物联网开发 来源:嵌入式物联网开发 作者:嵌入式物联网开发 2022-08-31 13:24 次阅读
相信大家当初学习C语言的时候,老师一定跟你说过这样的一句大实话:【**指针,是C语言的灵魂**】。

​ 笔者自出来工作以来,几乎天天都要跟C语言打交道,回过头来想一想,这话确实没有错。

​ 本文,打算从一个另类的角度,介绍下C语言指针的高级用法,通过本文的阅读,你将了解到以下知识:

  • C语言的指针是什么?
  • C语言指针的高级应用:函数指针
  • 函数指针的具体应用示例

C语言的指针是什么


​ 指针是什么?相信所有的C语言教程,都会告诉你:【指针就是地址】。没错,的确是这么回事。C语言的指针就好比房屋的地址,只要有了地址,我们就可以访问到全世界的每一个角落。C语言的世界也是如此,地址就是一切,有了地址,就没有干不成的事情。

​ 在C语言里,如果想对一个int类型的变量a进行赋值操作,我们会这样写: a = 5;这样的形式,就是直接访问。对应的,我们有间接访问的方式,就是通过指针来实现。比如我们可以定义一个指针 int *b = &a; 指针b存放的是a变量的地址,我们通过这样: *b = 5;一样可以实现对a进行赋值操作,这就是间接访问的力量。

​ C语言的指针是灵活的,它不仅可以像如上代码一样,指向一个普通变量,它也可以指向一个结构体变量,甚至还可以指向一个函数名。原因就在于,函数名,在C语言的语法里,本质上就代表了函数的执行地址,说白了,它也是一个“指针”。而这,就是我们以下要详细介绍的【函数指针】。


C语言指针的高级应用:函数指针


​ 【函数指针】,顾名思义,就是一个指向函数的指针,它的本质还是一个指针,只不过这个指针指向的内容是一个函数。

​ 在讲解【函数指针】之前,我们先假设有若干个函数,它们的原型定义如下所示:

int test_function_1(int arg);
int test_function_2(int arg);
int test_function_3(int arg);
...
int test_function_n(int arg);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NgxkHoX2-1661923373249)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 从函数原型上我们可以知道,这些个函数都是接收一个int类型的形参,返回值类型为int型。从原型上看,这几个函数几乎是一模一样,那么我们有没有方法可以将这些原型一致的函数重新整理定义呢?答案肯定是,有的。

​ 追求高效、简洁的C语言就我们提供了一个非常有用的关键字typedef,通过typedef我们可以重新创造出一个新的数据类型,而不再局限于C语言的基本数据类型。比如我们就可以利用typedef定义一个叫形如上述函数原型的【函数指针】数据类型,它的写法如下所示:

typedef int (*FUNCTION)(int arg);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MLEkQ9Bo-1661923373252)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 从定义上看,因为()拥有最高优先级,所以*FUNCTION首先结合在一起,这就决定了它是一个指针。接着,*FUNCTION的后面接上了(int arg),这就是函数的入参;而前面的int 就表示函数的返回值。这就是【函数指针】的原型定义。

​ 【函数指针】最为一种特殊的指针,自然它也是要指向内容才能使用的,毫无疑问,它就是要指向对应原型的函数。具体怎么使用呢?


函数指针的具体应用示例


​ 【函数指针】这种高阶用法,可能有些人用得比较少,但是如果你阅读过类似openssl这样的大型C语言编写的开源代码之后,相信你一定会感叹:原来,C语言的指针还能这么用!!!

​ 有了【函数指针】的利器,我们就可以用它来大做文章,请看以下示例代码:

int test_function_1(int arg)
{
    printf("This msg is printed form %s ...\n", __func__);
    return arg;
}

int test_function_2(int arg)
{
    printf("This msg is printed form %s ...\n", __func__);
    return arg;
}

int test_function_3(int arg)
{
    printf("This msg is printed form %s ...\n", __func__);
    return arg;
}

typedef int (*FUNCTION)(int arg);

int function_pointer_test_1(void)
{
    int ret;
    int arg = 1;
    FUNCTION func = NULL;        //定义个函数指针

    func = test_function_1;     //把函数指针指向test-function-1
    //ret = test_function_1(arg); //通过函数名直接调用test-function-1函数
    ret = func(arg);            //通过函数指针间接调用test-function-1函数

    func = test_function_2;     //把函数指针指向test-function-2
    //ret = test_function_2(arg); //通过函数名直接调用test-function-2函数
    ret = func(arg);            //通过函数指针间接调用test-function-2函数

    func = test_function_3;     //把函数指针指向test-function-3
    //ret = test_function_3(arg); //通过函数名直接调用test-function-3函数
    ret = func(arg);            //通过函数指针间接调用test-function-3函数

    return 0;
}

int function_pointer_test_2(void)
{
    int ret;
    int arg = 1;
    int i = 0;
    FUNCTION func = NULL;       //定义个函数指针
    FUNCTION func_array[] =     //定义一组函数列表
    {
        test_function_1,
        test_function_2,
        test_function_3,
    };

    //终极大招,循环处理3个函数的间接调用
    for (i = 0; i < sizeof(func_array); i ++) {
        func = func_array[i]; //把函数指针指向对应的函数
        ret = func(arg);      //通过函数指针间接调用对应的函数
    }

    return 0;
}

int main(int argc, char **argv)
{
    function_pointer_test_1();
    function_pointer_test_2();  

    /*
    结果输出,两个function_pointer_test函数均有同样的输出结果:
    This msg is printed form test_function_1 ...
    This msg is printed form test_function_2 ...
    This msg is printed form test_function_3 ...
    */

    return 0;
}

/*
总结:
虽然通过两个调用的方式,输出结果是一致的,但是显然方式2的处理更为高效、简洁;
从代码的字里行间,仿佛看到C语言的“多态”:将不同的函数名赋值给同一个函数指针变量;
使用同一个函数指针发起函数调用,得到不一样的结果输出,这不就是多态吗?
*/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oLznHZnb-1661923373260)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

​ 通过如上的示例代码,C语言的【多态】你get到了吗?


​ 千万不要小瞧了上面的示例代码,如果你能熟练掌握其中的【指针精髓】,再去阅读一些业内广泛使用的C语言编写的开源项目源码,比如大名鼎鼎的openssl;相信阅读之后,你的C语言功力一定会大大地提升。

​ 不过,值得注意的是,文中的示例代码均是笔者在编程环境下编写,属于【白板编程】,难免会出现编写错误、编译不过、或执行结果不正确的情况;还请细心的读者诚心指正,感激不尽。


延伸阅读预告:

为充实C语言的指针知识,笔者将会在后续的文章中整理大名鼎鼎的C语言巨著《C和指针》,敬请期待。

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7597

    浏览量

    136147
  • 指针
    +关注

    关注

    1

    文章

    479

    浏览量

    70506
  • 函数指针
    +关注

    关注

    2

    文章

    56

    浏览量

    3775
收藏 人收藏

    评论

    相关推荐

    C语言中指针的基本概念和用法

    C语言中,指针是一项重要的概念,它允许我们直接访问和操作内存地址。
    发表于 08-17 15:30 715次阅读

    C语言指针的高级用法

    C语言指针搞不好说实话实在是太麻烦的一个东西,而且C语言指针还是绕不过的一个坎,所以我觉得还是苦
    发表于 11-06 16:50

    C语言入门教程-指针

    指针C语言中,指针被广泛使用。所以要想完整地掌握C语言,您需要对
    发表于 07-29 11:30 656次阅读

    C语言指针电子教程

    本资料是一份不错的关于C语言指针的电子教程,希望对大家有所帮助... 指针简介 指针C
    发表于 07-30 16:00 77次下载

    C语言中指针的介绍非常详细

    C语言中指针的介绍非常详细 C语言中指针的介绍非常详细
    发表于 12-25 10:39 57次下载

    C语言指针函数和函数指针详细介绍

    C语言指针函数和函数指针详细介绍。。。。。。。
    发表于 03-04 15:27 5次下载

    C语言的精髓——指针详解

    C语言的精髓——指针详解
    发表于 11-30 14:43 17次下载

    基于C语言中指针的基本用法解析

    C语言中其它的知识都学得可以,唯独指针搞不懂。如果是这样,我可以很负责的告诉你,对于这门编程语言,你等于是没学。所以学好指针对于初学者是非
    的头像 发表于 01-09 15:12 4772次阅读

    C语言-一维指针定义与使用

    指针在很多书本上都是当做重点来介绍,作为C语言的灵魂,项目里指针无处不在。 这篇文章介绍指针的基本用法
    的头像 发表于 08-14 10:02 1304次阅读

    C语言进阶】sprintf和snprintf的区别

    C语言进阶】sprintf 和 snprintf 真的没有区别吗?
    的头像 发表于 08-31 13:18 1.2w次阅读

    C语言进阶】“数组指针”和“指针数组”都是啥跟啥?

    C语言进阶】“数组指针”和“指针数组”都是啥跟啥?
    的头像 发表于 08-31 13:21 1884次阅读

    C语言进阶】利用assert高效排查你的C程序

    C语言进阶】利用assert高效排查你的C程序
    的头像 发表于 08-31 13:27 2075次阅读

    详解C语言指针底层基本原理

    说到指针,估计还是有很多小伙伴都还是云里雾里的,有点“知其然,而不知其所以然”。但是,不得不说,学了指针C语言才能算是入门了。指针
    的头像 发表于 04-06 10:43 1204次阅读

    c语言指针用法详解:如何使用指针变量做函数参数

    指针C语言中一个比较重要的东西,有人说指针C语言的灵魂这句话说的一点也没错。 正确灵活地运用
    发表于 09-21 12:32 1038次阅读
    <b class='flag-5'>c</b><b class='flag-5'>语言</b><b class='flag-5'>指针</b><b class='flag-5'>用法</b>详解:如何使用<b class='flag-5'>指针</b>变量做函数参数

    C语言指针用法

    C语言编程中善用指针可以简化一些任务的处理,而对于一些任务(比如动态内存分配),必须要有指针才行的。也就是说精通C
    发表于 03-05 14:22 313次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>的<b class='flag-5'>指针</b><b class='flag-5'>用法</b>