【粉丝问答25】函数指针定义的一个错误

2023-11-16

1. 问题

某个函数指针的使用:编译时出错了。

type defaults to ‘int’ in declaration of ‘on_touch_messgae_handle’[-Wimplicit-int] typedef(*on_touch_messgae_handle)(touch_message_t);
问题 粉丝源码如下:
源码

2. 分析

1) 结构解析

 1 struct touch_message                                                        
  2 {
  3     rt_uint16_t x;
  4     rt_uint16_t y;  
  5     rt_uint8_t event;   
  6 };
  7 typedef struct touch_message * touch_message_t;
  8 typedef (*on_touch_messgae_handle)(touch_message_t);

首先看下7行这个类型定义:

typedef struct touch_message * touch_message_t;

定义后

touch_message_t 

等价于

 struct touch_message *

就是说我们如果用touch_message_t 定义的变量是一个struct touch_message类型的一个指针。

再来分析下8行这个定义:

typedef (*on_touch_messgae_handle)(touch_message_t);

可以替换成下面这个定义

typedef (*on_touch_messgae_handle)(struct touch_message *);

2) 分步解析

有的C语言基础不是很好的朋友,可能无法一眼看出来这个定义,
为了让新手更容易看懂,我们来看一下下面一个递进式的定义:

int fun;

这是一个整型变量fun;

int fun();

这是一个函数fun,
参数 : 空
返回值: int型

int fun(struct touch_message *);

这是一个函数fun,
参数 : struct touch_message *的一个指针
返回值: int型

上述的变化都好理解,下面我们将fun做如下修改:

int (*fun)(struct touch_message *);

括号的优先级最高,(fun)一旦如此定义,那么fun就要先和结合,
所以fun变成了一个指针,

那么该指针指向什么呢?
就需要看外面是如何定义的,
右边是(struct touch_message * ),左边是int,
所以说明指针指向的是一个函数,

参数 : struct touch_message *的一个指针
返回值: int型

举例:
将函数my_fun赋值给函数指针fun。
int my_fun(struct touch_message *)
{
}
int (*fun)(struct touch_message *);
fun = my_fun;

这里有一个隐藏的知识点,函数名其实也是一个地址,而且赋值的时候函数类型必须和函数指针类型一致。

typedef int (*fun)(struct touch_message *);

如果左边再加上typedef呢?
相当于是设置fun为新的类型,我们可以用fun来定义一个函数指针,
该函数类型同上。

举例
用新的类型定义一个函数指针变量,并给他赋值。
typedef int (*fun)(struct touch_message *);
int my_fun(struct touch_message *)
{
}
fun fun_ptr;
fun_ptr = my_fun;

然后将参数修改为,touch_message_t,就得到了粉丝的源码中的样子,

typedef int (*fun)(touch_message_t);

但是粉丝的源码中定义的函数类型缺少了对函数返回值的描述,所以左侧增加一个int或者其他类型即可即可。

3. 函数指针

函数指针在linux内核中使用非常频繁,

比如字符设备,内核给多有的字符设备提供了一个统一的接口,我们对设备的所有操作被抽象成read、write、open、close等,并封装到结构体struct file_operations 中:


struct file_operations {
	struct module *owner;
	loff_t (*llseek) (struct file *, loff_t, int);
	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	int (*iterate) (struct file *, struct dir_context *);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
	int (*mmap) (struct file *, struct vm_area_struct *);
	int (*open) (struct inode *, struct file *);
	int (*flush) (struct file *, fl_owner_t id);
	int (*release) (struct inode *, struct file *);
	int (*fsync) (struct file *, loff_t, loff_t, int datasync);
	int (*aio_fsync) (struct kiocb *, int datasync);
	int (*fasync) (int, struct file *, int);
	int (*lock) (struct file *, int, struct file_lock *);
	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file *, int, struct file_lock *);
	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
	int (*setlease)(struct file *, long, struct file_lock **);
	long (*fallocate)(struct file *file, int mode, loff_t offset,
			  loff_t len);
	int (*show_fdinfo)(struct seq_file *m, struct file *f);
};

那么我们应该如何定义该结构体变量并初始化呢?

static struct file_operations hello_ops = 
{
	.open = hello_open,
	.release = hello_release,
	.read = hello_read,
	.write = hello_write,
};

函数定义如下:

static int hello_open (struct inode *inode, struct file *filep)
{
	return 0;
}
static int hello_release (struct inode *inode, struct file *filep)
{
	return 0;
}

static ssize_t hello_read (struct file *filep, char __user *buf, size_t size, loff_t *pos)
{
	return size;
}
static ssize_t hello_write (struct file *filep, const char __user *buf, size_t size, loff_t *pos)
{
	return size;
}

注意,函数的参数和返回值,必须严格按照结构体struct file_operations中的类型定义。

加群,长按下面二维码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【粉丝问答25】函数指针定义的一个错误 的相关文章

  • Ubuntu/linux c开发(6)内存泄露

    写好个服务程序 短期测试没啥问题 准备跑长时间的 结果 前两天正常 第三天突然涨了100多M 这感觉 爽飞了 这里说下Ubuntu中内存泄露检测工具 Valgrind 安装和使用连接如下 链接 Valgrind安装使用 这里大概说下统计结果
  • 神经网络量化

    前言 神经网络在图像 语音识别等领域使用越来越广泛 大部分实时性要求不高的服务都可以部署在云上 然而还是有不少模型需要在计算能力有限的可移动设备上快速运行 如人脸解锁 拍照视频的实时处理等 一般训练的模型采用的都是32位浮点数 考虑到大部分
  • 第四讲 赋予网页样式

    文科编程系列课程 Web开发 第四讲 赋予网页样式 目录 引言 1 大小 1 1 长度单位 1 1 1 px 像素 1 1 2 百分比 1 2 宽高 1 1 1 宽度 1 1 2 高度 1 1 3 边框 2 颜色 2 1 颜色的三种表示形式

随机推荐

  • 毕业设计:自主开发的害虫识别系统--文档附源码

    基于yolov5多目标检测算法的农业害虫识别查询系统 设计文档 目标问题与意义价值 研究意义 本项目能够及时准确地识别农业害虫的种类 是害虫准确测报和合理防治的前提 传统的害虫识别方法主要依赖个人的专业经验进行辨别 或参考书本 网络上的文字
  • Qt5(一)编写Qt多窗口程序

    本文作者 小嗷 微信公众号 aoxiaoji 吹比QQ群 736854977 链接 https f600lt github io archives 摘要 这篇开始将从基础知识点开始一步一步QT到QT项目 原因就是读者说 QT类很多看不懂 这
  • 如何抵御ddos攻击-免费防御方法分享

    网站遭受DDOS攻击不要怕 今天来跟大家聊聊防御ddos攻击 顺便分享一些防御ddos攻击比较使用的方法 如果你是学生也不要紧 这里可以给你分享免费的防御方法 针对ddos攻击 我们升级服务器带宽配置是不起作用的 因为大部分攻击都是来自海外
  • 文心千帆为你而来

    1 前言 3月16号百度率先发布了国内第一个人工智能大语言模型 文心一言 文心一言的发布在业界引起了不小的震动 而文心一言的企业服务则由文心千帆大模型平台提供 文心千帆大模型平台是百度智能云打造出来的一站式大模型开发与应用平台 提供包括文心
  • 【面试题】说一下promise的理解

    一 什么是Promise ES6 异步编程的一种解决方案 比传统的方案 回调函数和事件 更加的合理和强大 大家都知道传统解决异步编程用的是回调函数套回调函数 简称回调地域 以前用JQuery的朋友应该是相当熟悉了 维护起来很难搞 回调地域
  • 七种Linux设备驱动模型之——Device

    前言 Linux将所有的设备统一抽象为struct device结构 同时将所有的驱动统一抽象为struct device driver结构 这样设计之后就方便驱动开发工程师编写驱动 只需要将具体的设备包含struct device结构 具
  • std::string用法总结

    在平常工作中经常用到了string类 本人记忆了不好用到了的时候经常要去查询 在网上摘抄一下总结一下 为以后的查询方便 string类的构造函数 string const char s 用c字符串s初始化string int n char
  • Windows10下Nginx初步配置

    1 nginx启动与关闭 nginx启动命令 一闪而过为正常启动 且看不到nginx进程 D server nginx nginx 1 16 0 gt start nginx nginx关闭命令 快速停止 nginx s stop 完整有序
  • 宝塔面板ip:端口,访问不进去;提示:请使用正确的入口登录面板 解决办法

    请使用正确的入口登录面板 错误原因 当前新安装的已经开启了安全入口登录 新装机器都会随机一个8位字符的安全入口名称 亦可以在面板设置处修改 如您没记录或不记得了 可以使用以下方式解决 解决方法 在SSH终端输入以下一种命令来解决 1 查看面
  • Android servicemanager进程启动过程

    在分析ServiceManager实例化注册流程前 先放张ServiceManager在Binder体系中的UML图 一 ServiceManager启动流程 查看system core rootdir init rc脚本可知 init进程
  • 用anaconda在d盘中创建虚拟环境

    我可以给你一些提示 首先 你需要在D盘中打开Anaconda Prompt 然后使用命令 conda create n python 来创建虚拟环境 其中 是你要为虚拟环境起的名字 而 则是你想安装的Python版本
  • 2023-9-11 拆分-Nim游戏

    题目链接 拆分 Nim游戏 include
  • 浅谈几个通信概念-如何理解卷积,负频率,傅里叶变换,奈奎斯特采样定理?

    1 如何理解卷积 t时刻的输出信号是t时刻之前的无数小的脉冲序列冲击引起的 2 如何理解欧拉公式 复指数信号呢 可以看成一个点在复平面上以角速度w进行逆时针的旋转 傅里叶分析 整体到部分 把一个信号分解成无数个基频组成的信号的和的过程 of
  • 7-4 输出三角形字符阵列 (15 分)

    7 4 输出三角形字符阵列 15 分 本题要求编写程序 输出n行由大写字母A开始构成的三角形字符阵列 输入格式 输入在一行中给出一个正整数n 1 n lt 7 输出格式 输出n行由大写字母A开始构成的三角形字符阵列 格式见输出样例 其中每个
  • 基于web的在线视频编辑的设计

    基于web的在线视频编辑的设计 我在这里首先说明一下 本设计只涉及到逻辑设计和关键的技术 具体的实现方法 语言就得运用自己的特长去解决了 场景 1 比如我用手机录播一段很长的MP4格式的视频 我想剪切其中的几段 然后在合并成一个新的视频 如
  • Hive(2) Hive单节点安装以及分布式安装

    Hive安装 单节点安装 在官网上下载Hive的安装包 官网地址 http hive apache org 把Hive的安装包上传到服务器中 然后解压到指定文件 我这里解压到 opt software 目录下 tar zxvf apache
  • C++11之第二章 2.23课后题讨论

    题目内容如下 给定指针p 你能知道它是否指向了一个合法的对象吗 如果能 叙述判断的思路 如果不能 也请说明原因 网上一下几种答案 答案1 这个问题我的思路是 首先用 p将其值输出来 如果编译器报错 证明p指向一个无效的对象 要么p 0要么p
  • Entity Framework 使用Code First 处理多个表关系时的错误 “将 FOREIGN KEY 约束 'FK_dbo.' 引入表 ' ' 可能会导致循环或多重级联路径”...

    将 FOREIGN KEY 约束 FK dbo 引入表 可能会导致循环或多重级联路径 请指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION 或修改其他 FOREIGN KEY 约束 WillCascad
  • Vue开发环境搭建全过程,一步一个坑

    这是基于vue cli 2 x 搭建项目 首先我们要安装好整个开发环境 其实Windows和Mac的整个过程基本一样 开发环境 Homebrew Mac的包管理神器 Node js cnpm 淘宝镜像 节省安装时间 webpack vue
  • 【粉丝问答25】函数指针定义的一个错误

    1 问题 某个函数指针的使用 编译时出错了 type defaults to int in declaration of on touch messgae handle Wimplicit int typedef on touch mess