C语言之回调函数+可变参数__VA_ARGS__:用法实例(四十八)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.C语言可变参数介绍
      • 🐓2.1 可变参数的含义
      • 🐓2.2 可变参数宏的用法
      • 🐓2.3 简单示例
      • 🐓2.4 用法注意
    • 🌻3.代码实例
      • 🐓3.1 可变参数为:一个参数
      • 🐓3.2 可变参数为:两个参数
      • 🐓3.3 可变参数简化版本V1.0

🌻1.前言

本篇目的:C语言之回调函数+可变参数:用法实例

🌻2.C语言可变参数介绍

  • 在C语言中,define call_void_hook(FUNC, ...)是一个可变参数宏的示例,它允许开发者调用一个函数FUNC,并将可变数量的参数传递给它。这种机制在C语言的标准库中非常常见,尤其是在处理像printf这样的函数时,它们可以接受不同数量和类型的参数。

🐓2.1 可变参数的含义

  • 可变参数意味着函数可以接受任意数量和类型的参数。在函数定义中,可变参数由省略号...表示。例如,printf()函数的原型是这样的:
int printf(const char *format, ...);
  • 这里,format是一个常规参数,而...表示printf()可以接受任意数量的其他参数。

🐓2.2 可变参数宏的用法

  • 要使用可变参数宏,你需要在宏定义中使用省略号...。例如,下面的宏定义接受一个函数名和任意数量的参数:
#define call_void_hook(FUNC, ...) FUNC(__VA_ARGS__)
  • 在这个宏定义中,FUNC是第一个参数,它应该是一个函数名。__VA_ARGS__是一个特殊的宏,它会在宏展开时被替换为宏调用中的实际参数列表。

🐓2.3 简单示例

#include <stdio.h>
void my_hook(int a, double b) {printf("Hook called with %d and %f\n", a, b);
}
int main() {call_void_hook(my_hook, 42, 3.14);return 0;
}
  • 在这个示例中,call_void_hook宏被用来调用my_hook函数,并传递两个参数:整数42和浮点数3.14。当宏被展开时,它会被替换为my_hook(42, 3.14)

🐓2.4 用法注意

  • 可变参数宏应该谨慎使用,因为如果使用不当,可能会导致不可预知的行为。
  • 在宏定义中,如果可变参数列表中包含逗号,那么在宏调用中这些逗号也需要保留。
  • 如果可变参数列表为空,那么在宏定义中省略号之前的逗号应该被删除或者用圆括号括起来。
  • C语言的可变参数功能为函数提供了极大的灵活性,使得函数可以处理不同数量的参数。然而,这也给程序员带来了更多的责任,确保正确使用可变参数,避免潜在的错误和漏洞。

🌻3.代码实例

🐓3.1 可变参数为:一个参数

#include <stdio.h>struct security_hook_list {void (*hook)(int);
};struct {struct security_hook_list FUNC;
} security_hook_heads;// 定义调用钩子的宏
#define call_void_hook(...)		\do {						\struct security_hook_list *P;		\P = &security_hook_heads.FUNC;		\if (P->hook)				\P->hook(__VA_ARGS__);			\} while (0)void my_hook_function(int arg) {printf("xxx--------------->%s(), line = %d, arg = %d\n",__FUNCTION__,__LINE__,arg);
}int main() {// 注册钩子函数security_hook_heads.FUNC.hook = my_hook_function;// 调用钩子函数call_void_hook(42);return 0;
}
  • security_hook_heads是一个全局变量,同时也是一个匿名结构体,它内部包含一个结构体security_hook_list,而结构体security_hook_list中定一个函数指针,返回值是void*,参数为int类型。
  • 定义宏call_void_hook,它的第一个参数是security_hook_list结构体类型,第二个…表示是可变参数。
  • 将全局变量security_hook_heads的FUNC成员赋值给指针P,因为在main函数中,已经将my_hook_function赋值给security_hook_heads.FUNC.hook。
  • 调用call_void_hook宏时,将参数42传入,调用 P->hook(VA_ARGS),其中__VA_ARGS__展开就是42.

🐓3.2 可变参数为:两个参数

#include <stdio.h>// 定义钩子函数的数据结构
struct security_hook_list {void (*hook)(int, char *);
};struct {struct security_hook_list FUNC;
} security_hook_heads;// 定义调用钩子的宏
#define call_void_hook(...)		\do {						\struct security_hook_list *P;		\P = &security_hook_heads.FUNC;		\if (P->hook)				\P->hook(__VA_ARGS__);			\} while (0)void my_hook_function(int arg, char *name) {printf("xxx--------------->%s(), line = %d, arg = %d, name = %s\n",__FUNCTION__,__LINE__,arg,name);
}int main() {// 注册钩子函数security_hook_heads.FUNC.hook = my_hook_function;// 调用钩子函数call_void_hook(42, "1234");return 0;
}

🐓3.3 可变参数简化版本V1.0

#include <stdio.h>// 定义钩子函数的数据结构
struct security_hook_list {void (*hook)(int, char *);
};struct {struct security_hook_list FUNC;
} security_hook_heads;//全局变量.#define call_void_hook(...)  security_hook_heads.FUNC.hook(__VA_ARGS__);void my_hook_function(int arg, char *name) {printf("xxx--------------->%s(), line = %d, arg = %d, name = %s\n",__FUNCTION__,__LINE__,arg,name);
}int main() {// 注册钩子函数security_hook_heads.FUNC.hook = my_hook_function;// 调用钩子函数call_void_hook(42, "1234");return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3012.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【linux】进程地址被占用

在强制关闭一个udp程序后&#xff0c;重启该程序报错&#xff1a; bind error: Address already in use 查找并关闭占用端口的进程&#xff1a; 首先&#xff0c;确定哪个进程占用了目标端口。在Linux系统中&#xff0c;可以使用以下命令&#xff1a; netstat -tulnp | grep …

【Linux网络】FTP服务

目录 一、FTP简介 1.FTP-文件传输协议 2.FTP的两种模式 二、安装配置FTP 1.安装环境 2.对文件的操作 3.切换目录 4.设置匿名用户 5.图形化界面登录 6.白名单与黑名单 重点与难点 一、FTP简介 1.FTP-文件传输协议 FTP是FileTransferProtocol&#xff08;文件传输协…

css中设置元素大小的属性block-size

block-size 是 CSS 中的一个属性&#xff0c;它用于设置元素的块级尺寸&#xff08;即元素的高度&#xff09;。这个属性是 height 和 max-height 的逻辑组合&#xff0c;允许你同时设置元素的最小和最大高度。 这些属性旨在让布局不再依赖于传统的物理方向&#xff08;如上下左…

如何调节电脑屏幕亮度?让你的眼睛更舒适!

电脑屏幕亮度的调节对于我们的视力保护和使用舒适度至关重要。不同的环境和使用习惯可能需要不同的亮度设置。可是如何调节电脑屏幕亮度呢&#xff1f;本文将介绍三种不同的电脑屏幕亮度调节方法&#xff0c;帮助您轻松调节电脑屏幕亮度&#xff0c;以满足您的需求。 方法1&…

hbase 集成 phoenix 实现 sql 化

1. 依赖 hbase > hbase 集群搭建 2. 下载安装包 点击下载 ps&#xff1a;该网页在内网可能打不开&#xff0c;遇到该情况有条件的可以打开 VPN 在下载 3. 上传解压 使用工具将安装包上传的服务器上 笔者这里选择 上传到 /opt/software 目录&#xff0c;解压到 /opt/mo…

spring security登录认证授权

spring security登录认证授权 是什么 Spring Security 主要实现了Authentication&#xff08;认证&#xff0c;解决who are you? &#xff09; 和 Access Control&#xff08;访问控制&#xff0c;也就是what are you allowed to do&#xff1f;&#xff0c;也称为Authorizat…

C语言扫雷游戏完整实现(下)

文章目录 前言一、排雷函数菜单二、排雷函数菜单的实现三、拓展棋盘功能四、源码1. test.c源文件2. game.h头文件3. game.c源文件 总结 前言 C语言实现扫雷游戏的排雷菜单&#xff0c;以及功能的实现&#xff0c;拓展棋盘功能&#xff0c;以及源码等。 上半部分的链接地址: C语…

python 笔记ast.literal_eval

1 介绍 ast.literal_eval 是 Python 标准库 ast 模块中的一个函数&#xff0c;用于安全地评估表示 Python 字面量或容器&#xff08;如列表、字典、元组、集合&#xff09;的字符串 import ast # 解析并执行一个数字表达式 num ast.literal_eval("3.14") prin…

新媒体运营-----短视频运营-----PR视频剪辑----软件基础

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1.1 PR软件重置与初始化设置1.2 新建项目及序列设置1.3 PR工作区的管理方法1.4 导入4K超高清视频并与ME配合工作1…

远程监控与控制的融合:吊车远程视频监控与远程开机的实现

随着信息技术的飞速发展&#xff0c;远程控制技术已经广泛应用于各个领域&#xff0c;包括工业、医疗、教育等。吊车远程视频监控作为远程控制的一种具体应用&#xff0c;不仅实现了对吊车操作的实时监控&#xff0c;还通过与远程开机功能的结合&#xff0c;进一步提升了远程控…

ctfshow web41-web50

web41 代码审计 <?php if(isset($_POST[c])){$c $_POST[c]; if(!preg_match(/[0-9]|[a-z]|\^|\|\~|\$|\[|\]|\{|\}|\&|\-/i, $c)){eval("echo($c);");} }else{highlight_file(__FILE__); } ?> 过滤了&#xff1a;[0-9] [a-z] ^ ~ $ [ ] { } & -…

Python自动化系统6

元素的特征:根据页面设计规则&#xff0c;有些特征是唯一 开发遵循了这个规则 id :类比身份证号―仅限于当前页面 username username 注意:如果id 不是固定的话&#xff0c;就不能使用来定位! xpath: 1、绝对路径&#xff1a;/html/body/div/div/div[1]/a/b --根节点&#xff…

初始Maven

1.背景 问题引入&#xff1a;为什么要使用 Maven&#xff1f; 1.1 添加第三方 jar 包 在 JavaEE 开发领域&#xff0c;有大量的第三方框架和工具可以供我们使用。使用这些 jar 包最简单的方法就是复制粘贴到 WEB-INF 目录中的 lib 目录下。但是会导致每次创建一个新工程就需要将…

基于python+django+mysql农业生产可视化系统

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

数据结构系列-堆排序当中的T-TOK问题

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 之前我们讲到了堆排序的实现逻辑&#xff0c;那么接下来我们重点关注的就是其中的T-TOK问题 T-TOK说简单点&#xff0c;就是说&#xff0c;假如有10000个数据&#xff08;随机的…

Vue3后台管理系统推荐

目录 项目概述 &#x1f35f; 项目展示 功能特点 &#x1f957; 结语 &#x1f4a8; 项目概述 &#x1f35f; 基于Vue 3框架与Element-Plus UI组件库技术精心构建的后端管理模板。该模板系统已成功实现一个基础的权限管理模块&#xff0c;宗旨在于为追求高效二次开发的开发…

hsql数据库(HyperSQL )(简单了解一下)

文章目录 一、HyperSQL &#xff08;HSQLDB&#xff09;1、HSQLDB是什么2、安装事务提一嘴特点看官网Datagrip连接HSQLDBMaven地址使用场景 参考文章 一、HyperSQL &#xff08;HSQLDB&#xff09; 1、HSQLDB是什么 HSQLDB (Hyper SQL Database)是一个用Java编写的关系数据库管…

SpringBoot---------整合Mybatisplus

快速入门 第一步&#xff1a;导入依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency> 第二步&#xff1a;编写mapper…

【C++题解】1632. 需要几辆车

问题&#xff1a;1632. 需要几辆车 类型&#xff1a;分支 题目描述&#xff1a; 学校有 n 位同学要外出旅游&#xff0c;一辆大巴车可以坐 30 人&#xff0c;请问需要几辆大巴车&#xff1f; 输入&#xff1a; 一个整数 n&#xff0c;代表同学的总人数。 输出&#xff1a;…

明日方舟游戏助手:一键完成日常任务 | 开源日报 No.233

MaaAssistantArknights/MaaAssistantArknights Stars: 11.6k License: AGPL-3.0 MaaAssistantArknights 是一款《明日方舟》游戏的小助手&#xff0c;基于图像识别技术&#xff0c;支持一键完成全部日常任务。 刷理智、掉落识别及上传企鹅物流智能基建换班、自动计算干员效率…