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);

最终结果为:

时间: 2024-10-22 17:21:56

C语言中函数指针数组浅析的相关文章

C语言中函数返回数组

#include "stdio.h"/*int* set(int a,int *c){ int *b; b=malloc(sizeof(int)*3); c[0]=a; c[1]=1+a; c[2]=2+a; b[0]=13; b[1]=14; b[2]=15; return b;}*/char *set(void){ char *buf; buf=malloc(sizeof(char)*3);//创建内存区 buf[0]=0x30; buf[1]=0x31; buf[2]=0x32;

C语言的函数指针数组(好绕啊~)

int *(*p(int))[3] 今天有人问这个是啥?我一看直接就懵逼了…… 下面做一些简单的分析. int p; //这是整数型变量p int *p; //这是整数型指针p int *p[3]; //这是长度为3的整数型指针数组p,元素为整数型指针 int (*p)[3]; //这是一个数组指针,指向一个长度为3的整数型数组 int p(int); //这是函数声明,形参:整数型 ,返回值:整数型 等同于 int p(int x); int *p(int); //这是函数声明,形参:整数型

C语言中函数指针

函数调用的方法有两种分别如下: void Fun(void) { //do something } int main(void) { ... Fun(); ... return 0; } void Fun(void) { //do something } int main(void) { ... void (*p)(void); p=Fun; p(); return 0; } 上面两种方式都可以调用函数,第二种方式在回调函数中用的最多,尤其是在操作系统的任务切换中.那么我们就重点来分析下第二种方

C语言中的指针数组和数组指针

代码: 1 #include <iostream> 2 3 using namespace std; 4 int main(){ 5 6 int *a[10]; 7 int (*b)[10]; 8 cout<<sizeof(a)<<endl; 9 cout<<sizeof(b)<<endl; 10 11 cout<<a<<" "<<a+1<<endl; 12 cout<&l

c语言中函数指针和指针函数

一.什么是函数指针: 函数指针本质上也是指针,我们所写函数代码在内存中会被分配一段专门的储存空间,这段储存空间的地址就是函数的地址,既然是地址,就可以用指针去表示,自然就有了函数指针. 二.函数指针的用法: 1.首先明确函数指针怎么申明.形如:返回值类型 (*变量名)(参数类型1,参数类型2,...) 例如 int (*p) (int,int) 2.我们还需要了解如何通过指针调用函数. (*p)(3,5); 3.如何给该类型的指针赋值: 非常简单,直接将函数名赋给指针即可,因为函数名即为函数的首

C语言中函数指针与指针函数的区别和实际应用

1.指针函数 指针函数是返回指针的函数,主体是函数,返回值是一个指针   基本声明形式:返回数据类型 + * + 函数名 + (变量类型1,…); int* fun(int,int); int * fun(int,int); int *fun(int,int); 这三种声明都可以,第一种更加直观 返回值是 int* 类型. #include<stdio.h> int* fun(int* x) //传入指针 { int* tmp = x; //指针tmp指向x return tmp; //返回t

C#委托与C语言函数指针及函数指针数组

C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用的时候通过指针访问这个函数. 在C语言中函数指针的申明如下: //可以理解为申明一个指着变量 Func ,它的类型是 返回Type(可以为 void )类型的参数,接收 (Type one,Type two,...)类型的//参数(可以不接受参数). Type *Func(Type one,Type

C语言基础知识----指针数组 &amp;&amp; 数组指针 &amp;&amp; 函数指针 &amp;&amp;指针函数

指针数组 && 数组指针 char (*ptr)[5]; //定义一个指向数组指针ptr,指向包含5个char类型的数组 char *a[5]; //定义一个指针数组a,包含5个char*类型指针 #include <stdio.h> int main(void) {     char *a[5]={"red","white","blue","dark","green"};   

C语言中函数和指针的参数传递

最近写二叉树的数据结构实验,想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个例子讨论一下c语言中指针作为形参的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个数据引用同一个数据,那么更改任意的一个都相当于更改了本体,那么另一个数据所对应的值也会改变,可是C中是没有这个概念的.所以就产生了一些东西.和我们本来想的有差别. 一.明确C语言中函数的入口: C语言中函数的形参负责接收外部数据,那么数据究竟怎么进入函数的呢,其实我们在函数体内操作的形参只是传递进来