C语言中函数指针数组浅析

简介:
  • 发现问题
  • 问题分析
  • 示例代码

发现问题

今天,在阅读Linux内核中关于socket的源代码时,遇到了下面一段代码:

struct proto_ops {
    int family;
    struct module *owner;
    int (*release)   (struct socket *sock);
    int (*bind)      (struct socket *sock,
                      struct sockaddr *myaddr,
                      int sockaddr_len);
    int (*connect)   (struct socket *sock,
                      struct sockaddr *vaddr,
                      int sockaddr_len, int flags);
    int (*socketpair)(struct socket *sock1,
                      struct socket *sock2);
    int (*accept)    (struct socket *sock,
                      struct socket *newsock, int flags);
    int (*getname)   (struct socket *sock,
                      struct sockaddr *addr,
                      int *sockaddr_len, int peer);
    unsigned int (*poll)     (struct file *file, struct socket *sock, 
                              struct poll_table_struct *wait);
    int (*ioctl)     (struct socket *sock, unsigned int cmd, unsigned long arg);
    int (*listen)    (struct socket *sock, int len);
    int (*shutdown)  (struct socket *sock, int flags);
    int (*setsockopt)(struct socket *sock, int level,
                      int optname, char __user *optval, int optlen);
    int (*getsockopt)(struct socket *sock, int level,
                      int optname, char __user *optval, int __user *optlen);
    int (*sendmsg)   (struct kiocb *iocb, struct socket *sock,
                      struct msghdr *m, size_t total_len);
    int (*recvmsg)   (struct kiocb *iocb, struct socket *sock,
                      struct msghdr *m, size_t total_len,
                      int flags);
    int (*mmap)      (struct file *file, struct socket *sock,
                      struct vm_area_struct * vma);
    ssize_t (*sendpage)  (struct socket *sock, struct page *page,
                      int offset, size_t size, int flags);
};

在这段代码中,我们注意到proto_ops结构体的成员包括下面这样的成员变量:

int (*release)   (struct socket *sock);

这边是函数指针作为结构体成员变量的使用方法。

问题分析

首先,我们对C和C++中结构体以及C++类的区别进行一些说明:

C中的结构体和C++中结构体的不同之处:
在C中的结构体只能自定义数据类型,结构体中不允许有函数;
而C++中的结构体可以加入成员函数。

C++中的结构体和类的异同:
相同之处:
结构体中可以包含函数;也可以定义public、private、protected数据成员;定义了结构体之后,可以用结构体名来创建对象。但C中的结构体不允许有函数;也就是说在C++当中,结构体中可以有成员变量,可以有成员函数,可以从别的类继承,也可以被别的类继承,可以有虚函数。

不同之处:
结构体定义中默认情况下的成员是public,而类定义中的默认情况下的成员是private的。类中的非static成员函数有this指针,(struct中没有是错误的,一直被误导啊,经过测试struct的成员函数一样具有this指针),类的关键字class能作为template模板的关键字,而struct不可以。

实际上,C中的结构体只涉及到数据结构,而不涉及到算法,也就是说在C中数据结构和算法是分离的,而到C++中一类或者一个结构体可以包含函数(这个函数在C++我们通常中称为成员函数),C++中的结构体和类体现了数据结构和算法的结合。
因此,我们在阅读纯C代码时,应该注意代码中使用函数指针成员变量来等效地实现成员函数过程。

示例代码

这里,我们使用一段代码来对函数指针成员进行相关说明:

#include <stdio.h>
#include <stdlib.h>

int func1(int n)
{
    printf("func1: %d\n", n);
    return n;
}

int func2(int n)
{
    printf("func2: %d\n", n);
    return n;
}

int main()
{
    int (*a[2])(int);
    a[0] = func1;
    a[1] = func2;
    a[0](1);
    a[1](2);

    return 0;
}

我们注意上面代码中的

int (*a[2])(int);

在这句代码中,我们定义了这样一个数组:

数组保存指针,什么样的指针呢?
形如 int func(int input) 的 func函数指针,形参为int变量,返回int变量。
因此,数组保存的是形参为单一int变量和返回值为int值得函数指针。

现在,我们定义了这样一个数组,然后

    a[0] = func1;
    a[1] = func2;

由于我们在main函数前声明和定义了func1和func2两个函数(这两个函数满足前面所提及的函数条件),这时,我们便可以使用这两个函数指针赋值函数指针数组。
然后,我们便可以使用数组成员来实现函数调用:

    a[0](1);
    a[1](2);

最终结果为:
这里写图片描述

目录
相关文章
|
1月前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
86 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
1月前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
56 9
|
1月前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
45 7
|
1月前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
98 6
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
71 5
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
159 13
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
135 3
|
2月前
|
存储 C语言 开发者
C 语言指针与内存管理
C语言中的指针与内存管理是编程的核心概念。指针用于存储变量的内存地址,实现数据的间接访问和操作;内存管理涉及动态分配(如malloc、free函数)和释放内存,确保程序高效运行并避免内存泄漏。掌握这两者对于编写高质量的C语言程序至关重要。
63 11
|
2月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。