尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
C语言如何实现C++的默认参数方法
前言在C里在声明一个函数时可以显示给参数指定默认参数值voidadd(inta,intb2)这样你直接调用add(1)编译器在构建的时候会默认给第二个参数传递2但是C语言没有这样的能力C语言是一个面向底层的语言它不具备那么多花里胡哨的特性但是我们可以通过宏的方法来实现C语言里宏给我们提供了极大的灵活性开发特别是在Linux、Zephyr这样的操作系统里经常会使用到宏来包装实现API。宏的可变参数计算方法我记得很久之前我看到过Zephyr的一段源码它为unit test提供的一套API是经过宏包装的主要功能是通过宏来指定数量来生成指定数量级的测试函数例如一个宏展3个Test函数不需要自己去手写多个其目的是为了测试一个API传递多个递阶数所以这里先讲解一下如何利用宏来实现可变参数计算方法。首先可以先看一段代码这段代码是我最近为项目设计的日志模块所编写的这里我简化了一下它的实现目的是为了教学如何通过宏计算可变参数#defineFAST_LOG_PRINT_NUMBER(_0,_1,_2,_3,_4,_n,...)_n#defineFAST_LOG_MERG(...)FAST_LOG_PRINT_NUMBER(_,##__VA_ARGS__,\4,3,2,1,0)#defineFAST_LOG_CART_TRUE(a,b)a##b#defineFAST_LOG_CART(a,b)FAST_LOG_CART_TRUE(a,b)#defineFAST_LOG_PRINT(...)FAST_LOG_CART(FAST_LOG_PRINT_,\FAST_LOG_MERG(__VAR_ARGS__))(__VAR_ARGS__)#defineFAST_LOG_PRINT_0()//0#defineFAST_LOG_PRINT_1(_1)//1#defineFAST_LOG_PRINT_2(_1,_2)//2#defineFAST_LOG_PRINT_3(_1,_2,_3)//3#defineFAST_LOG_PRINT_4(_1,_2,_3,_4)//4这个宏计算最大支持4个参数传递同时也支持传递空参数那么接下来来说一下这一段的实现原理其核心函数就两个FAST_LOG_PRINT_NUMBER(_0,_1,_2,_3,_4,_n,...)_nFAST_LOG_MERG(...)FAST_LOG_PRINT_NUMBER(_,##__VA_ARGS__,\4,3,2,1,0)FAST_LOG_MERG输入的是可变参数然后将__VA_ARGS__传递给FAST_LOG_PRINT_NUMBER这个函数是推导宏推导出有几个参数然后决定使用哪个FAST_LOG_PRINT这里推导的思路也非常简单FAST_LOG_MERG最终只输出_n而FAST_LOG_MERG在调用FAST_LOG_PRINT_NUMBER的时候假如给的是FAST_LOG_PRINT_NUMBER(0, 1, 2)那么最终宏翻译就是FAST_LOG_PRINT_NUMBER(_, 0, 1, 2, 4, 3, 2) 2最终这里的_n就变成了2这里其实就是利用一个巧妙的挤数字方法因为FAST_LOG_PRINT_NUMBER里面__VA_ARGS__后面紧跟着顺序数字依次递减当__VA_ARGS__参数越多后面的数字递增到N的就越大这样就能计算出到底有多少个参数了。其中最前面的__这个是为了解决0参数时候也就是调用宏不给参数时默认给一个0让_n这个数字变为0。那么通过这个实现我们就可以实现给默认缺省参数了在FAST_LOG_PRINT_0、FAST_LOG_PRINT_1、FAST_LOG_PRINT_2调用不同函数时来依次传递不同参数例如有一个set_sys_config的api可以封装为:FAST_LOG_PRINT_0() set_sys_config(a, b, c, d)#define FAST_LOG_PRINT_1(_1) set_sys_config(_1, a, b, c)在调用时只需要调用FAST_LOG_PRINT即可FAST_LOG_PRINT(); //无参数FAST_LOG_PRINT(“hello world”); //1个参数这样就实现类似c的缺省参数其实这个方法在Linux/zephyr里也有用过不过不是用于缺省缺省只是这种开发方法应用场景的其中一个在内核里多数用于例如写test case要写许多非常多的重复代码那么这个时候就可以利用这种方法来动态生成不同参数级别的test case func。
RELATED

相关推荐

C++ boost::lambda 详解:从入门到实战

C++ boost::lambda 详解:从入门到实战

C boost::lambda 详解:从入门到实战引言1、 核心概念与原理1.1、 什么是 Lambda 表达式?1.2 、占位符(Placeholders)1.3 、延迟计算(Lazy Evaluation)2、 环境配置与基本用法2.1 、包含头文件2.2 、第一个例…

📅 2026/10/5 4:08:18
第三:Pytest-setup/teardown的类型种类

第三:Pytest-setup/teardown的类型种类

一.简介 1.unittest里面用前置和后置setup和teardown非常好用,在每次用例开始前和结束后都去执行一次2.当然还有更高级的setupClass和teardownClass,需配合classmethod装饰器一起使用 2.1.在做selenium自动化的时候,它的效率尤为突出&#xf…

📅 2026/9/16 19:29:17
彻底搞懂 K8s 服务访问:ClusterIP、NodePort 流量机制

彻底搞懂 K8s 服务访问:ClusterIP、NodePort 流量机制

前言在 Kubernetes 集群中,Pod 是最小的部署单元,但 Pod 的生命周期是短暂的——当 Pod 发生故障或被重新调度时,其 IP 地址也会随之改变。这就带来一个问题:如果一组 Pod 需要对外提供稳定服务(例如 HTTP 服务&#x…

📅 2026/10/8 14:45:01
MORE NEWS

更多资讯

📰

Delphi XE10.2 安装 TMS Component Pack v8.3.4.0 兼容指南

简介:本资源为Delphi XE10.2 Tokyo平台专用的TMS Component Pack v8.3.4.0完整开发组件包,面向中高级Windows桌面及跨平台(Android/iOS)Delphi开发者,解决UI构建、数据绑定、图表可视化、数据库导航等高频开发需求。压…

📰

Delphi 7 直连 MySQL:mysql.dll 原生调用实战指南

简介:本资源面向Delphi中高级开发者,聚焦于绕过OLE DB、直接调用MySQL原生客户端库(mysql.dll)实现数据库连接与操作的核心技术实践。它解决了在Windows平台下Delphi程序高效、轻量、跨版本兼容地访问MySQL的实际工程问题&#xf…

📰

OJ题解代码包全解析:从AC代码到算法避坑指南

简介:杭州电子科技大学在线OJ平台1000~1099号题目的C/C题解合集,按难度递增收录约百道经典编程题,适合算法竞赛入门者、刷题练习者及备考复试的上机考生。压缩包共90个文件,以源代码为主:62个cpp和16个c分别…

📰

Delphi Berlin下安装Raize 6.1.1.12完整指南:解决老组件库兼容性问题

简介:这套Raize 6.1.1.12组件包是针对Delphi 10.1 Berlin环境的修正发布版,主要面向使用Raize可视化控件的桌面应用开发者。原版安装后常因pas文件错误导致编译失败,作者已修正相关单元并调整配置文件,解压至C:\Program Files\Rai…

📰

6G网络架构设计实战:三层四面与四个网络单元详解

简介:这份PDF白皮书由中国电信研究院与中兴通讯于2023年联合发布,面向通信网络研究者、架构师及高校师生,系统探讨6G网络的设计理念、总体架构与创新特征,为理解下一代通信网络提供前瞻性参考。资源包内仅含1个PDF文件&#xff0c…

📰

基于深度 Q 网络(DQN)的 GPU 显存智能超卖与碎片重整理:大模型推理集群算力优化

在大语言模型(LLM)与生成式人工智能全面进入企业级生产核心链路的今天,由数百台配备了顶级 GPU(如 NVIDIA A100、H100、H800)组成的异构算力集群,已经成为企业 IT 预算中最为昂贵的“吞金巨兽”。单台八卡高…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬