【C/C++】 变参函数
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#define MLA_ASSERT(expr) (int)((!!(expr)) && (printf("assert fail: \"%s\" @ %s, %u", #expr, __FILE__, __LINE__), printf("\r\n"), Abort()))
int Abort(void)
{
printf("reset reboot!\n");
// 重启代码
}
/**
* 按自定义格式符解析数据
*/
void process(const char *fmt, va_list args)
{
CHECK(fmt != NULL);
for (; *fmt; fmt++) {
if (*fmt == '%') {
switch (*++fmt) {
case 'a':
case 's': {
char *str = va_arg(args, char *);
printf("%s", str);
continue;
}
case 'b': {
float *num = va_arg(args, float *);
printf("%f", *num);
continue;
}
case 'f': {
float num = va_arg(args, double); // 解析浮点数须用double,不能用float
printf("%f", num);
continue;
}
default:
printf("%c", *fmt);
continue;
}
} else {
printf("%c", *fmt);
}
}
}
/**
* 自定义可变参数函数
* @param hint: 传递给函数的额外参数
* @param fmt: 自定义格式符
*/
void VariadicFunction(char *hint, const char *fmt, ...)
{
MLA_ASSERT(hint == NULL);
MLA_ASSERT(fmt == NULL);
// 定义有个参数列表
va_list args;
// 初始化列表参数args,第二个参数可变参数前的第一个固定参数,即略号前的第一个参数
va_start(args, fmt);
// 解析数据
process(fmt, args);
// 释放可变参数列表
va_end(args);
// 额外参数处理
printf("%s, hint: %s\n", __func__, hint);
}
/**
* 带缺省参数可变参数函数
* @param hint: 传递给函数的额外参数
* @param isPrint: 带缺省属性的参数
* @param number: 带缺省属性的参数
*/
void DefaultVariadicFunction(char *hint, bool isPrint = false, int number = 666)
{
MLA_ASSERT(hint == NULL);
printf("%s, hint: %s\n", __func__, hint);
if (isPrint) {
printf("%s, This is a function with default arguments: %d\n", __func__, number);
}
}
void PackageFormattingData(char *hint, const char *fmt, ...)
{
MLA_ASSERT(hint == NULL);
MLA_ASSERT(fmt == NULL);
char buf[256] = { 0 };
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
printf("%s, hint: %s\n", __func__, hint);
// file_write(buf);
printf("%s, content: %s\n", __func__, buf);
}
int main()
{
float f = 6.66;
VariadicFunction("Here's a hint!", "%a%b%f%a", "string1", &f, 9.99, "STRING2");
DefaultVariadicFunction("Here's a hint!");
DefaultVariadicFunction("Here's a hint!", true);
DefaultVariadicFunction("Here's a hint!", true, 999);
PackageFormattingData("Can be used for writing files!", "%d, %f, %c, %s", 666, 88.88, 'C', __func__);
PackageFormattingData("Can be used for writing files!", "%c, %s", 'F', "You can refer to the use of files as logs on the back end.");
return 0;
}

自定义变参函数需要加入参数格式检查,以便在编译期就发现问题,避免运行时参数问题导致的异常
Function Attributes - Using the GNU Compiler Collection (GCC)

void __attribute__((format(printf,2,3))) VariadicFunction(char *hint, const char *fmt, ...)
{
MLA_ASSERT(hint == NULL);
MLA_ASSERT(fmt == NULL);
// 定义有个参数列表
va_list args;
// 初始化列表参数args,第二个参数可变参数前的第一个固定参数,即略号前的第一个参数
va_start(args, fmt);
// 解析数据
process(fmt, args);
// 释放可变参数列表
va_end(args);
// 额外参数处理
printf("%s, hint: %s\n", __func__, hint);
}
VariadicFunction("Here's a hint!", "function name: %s");
加了参数格式化检查就会在编译时给出一个warning

【C/C++】 变参函数的更多相关文章
- C++ 可变参函数实现
先简单总结一下基本的用法: void sum(int n, ...) { va_list arg_ptr = NULL; //申请一个指针 va_start(arg_ptr, n); //设置指针指向 ...
- C/C++中的可变参函数
可变参函数最好的实例:printf();参数可变 包含的头文件: C语言中:#include<stdarg.h> C++中的可变参的头文件:#include<cstdarg>, ...
- C语言变参函数/Variadic fucntion
几个重要的 宏/类型 定义 Macros Defined in header <stdarg.h> va_start enables access to variadic function ...
- Objective-C实现变参函数
原文:http://www.tanhao.me/pieces/1104.html NSLog(NSString *format, ...) + (id)arrayWithObjects:(id ...
- C 语言精髓之变参函数
我们以 printf 这个 very 熟悉的函数为例,来分析一下变参函数.先看下 printf 函数的定义: int printf(const char *fmt, ...) { int i; int ...
- java基础---->java中变参函数的使用
Java的变参函数实现实际上参数是一个数组,今天我们就简单的学习一下它的用法. java中的变参函数 一.它的使用方法如下: public class VariableParam { private ...
- 嵌入式C语言自我修养 08:变参函数的格式检查
8.1 属性声明:format GNU 通过 __atttribute__ 扩展的 format 属性,用来指定变参函数的参数格式检查. 它的使用方法如下: __attribute__(( forma ...
- va_start、va_arg、va_end、va_copy 可变参函数
1.应用与原理 在C语言中,有时我们无法给出一个函数参数的列表,比如: int printf(const char *format, ...); int fprintf(FILE *s ...
- Golang教程:函数、变参函数
函数是完成一个特定任务的代码块.一个函数接受输入,对输入进行一些运算并产生输出. 函数声明 在 Go 中声明一个函数的语法为: func functionname(parametername type ...
- C语言变参函数的实现原理
1. 变参函数简单示例 #include <stdarg.h> #include <stdio.h> int Accumlate(int nr, ...) { ; ; va_l ...
随机推荐
- 年度盘点,四年的精华合集「GitHub 热点速览」
今年是 GPT 年,无论是 GitHub 还是朋友圈还是技术平台,即便你不关心 GPT 的发展情况,同大模型.AI 相关的项目总能进入你的信息流.到这期为止,热度速览也连载了四年,从一开始习惯看 Gi ...
- 设计模式Java实战,彻底学会
这是全网最强的Java设计模式实战教程.此教程用实际项目场景,结合SpringBoot,让你真正掌握设计模式. 网址是:Java设计模式实战专栏介绍 - 自学精灵(也可以百度搜索"自学 ...
- Java反序列化漏洞-CC1利用链分析
@ 目录 一.前置知识 1. 反射 2. Commons Collections是什么 3. 环境准备 二.分析利用链 1. Transformer 2. InvokeTransformer 执行命令 ...
- WinForm如何将子控件插入FlowLayoutPanel开始位置
需求描述 动态将控件插入到FlowLayoutPanel控件的开始位置 实现方案 将控件添加到FlowLayoutPanel的Controls集合中,默认插到末尾 使用SetChildIndex方法更 ...
- 神经网络入门篇:深度学习和大脑的关联性(What does this have to do with the brain?)
深度学习和大脑的关联性 开始讲故事(手动狗头) 深度学习和大脑有什么关联性吗? 关联不大. 那么为什么会说深度学习和大脑相关呢? 当你在实现一个神经网络的时候,那些公式是你在做的东西,你会做前向传播. ...
- 案例集锦|科技赋能,华为云GaussDB助千行百业数字化转型
当下,全社会驶入数字化转型快车道,以科技赋能.智慧转型为主旨的数字生态推动着千行百业的变革.数据库作为企业核心数据底座,华为云提供了安全可靠的云原生底座和一站式上云解决方案.其中华为云GaussDB覆 ...
- 云图说 | Workflow:流水线工具,助您高效完成AI开发
摘要:Workflow是将ML Ops(机器学习和DevOps的组合实践)应用于ModelArts平台,可以让您更高效的完成AI开发. 本文分享自华为云社区<云图说 | 第263期 Workfl ...
- 详解JQuery框架的五大选择器
摘要:今天来和大家分享一下JQuery的五种选择器的详细使用方法. 本文分享自华为云社区<[JQuery框架]五大选择器"全家桶"详解!!!>,原文作者:灰小猿 . 今 ...
- VS 进行了无法编译的编辑
Debug的时候碰到这个很烦人得重新运行 工具=>选项=>常规=>调试=>常规 将启用"编辑"并继续,勾取消掉
- 使用root ssh登录ubuntu22.4配置
前言 在安装k8s集群时,需要使用root用户ssh登录远程服务器进行安装操作,但是root登录是默认关闭的,因此本篇讲解如何开启配置, 当前测试版本 ubuntu22.4 安装部署 使用管理权限打开 ...