【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 ...
随机推荐
- 数字孪生为何需要融合GIS?以智慧城市项目为例说明
数字孪生和地理信息系统(GIS)是两个在现代科技中崭露头角的概念,它们的融合为智慧城市项目带来了革命性的机会.本文将解释数字孪生为何需要融合GIS,并以智慧城市项目为例进行说明. 数字孪生是一种虚拟模 ...
- Postgres服务器操作方法
切换用户 sudo su postgres psql postgres 查询当前postgres下的DB列表 \l 查看postgres下角色的详细信息(权限) \du 删除odoo角色 drop r ...
- rcs群发软件系统功能设计与应用,rcs群发软件系统,rcs群发软件
随着科技的不断发展,人们对于通讯方式的需求也在不断变化,传统的短信.电话已经无法满足人们对于高效.便捷.实时的通讯需求,正是在这样的背景下,富通讯解决方案(Rich Communication Sui ...
- 从零玩转xxl-job分布式任务调度-xxl-job
title: 从零玩转xxl-job分布式任务调度 date: 2022-03-18 00:11:55.443 updated: 2023-01-05 10:58:06.991 url: https: ...
- Flutter Getx 状态管理 --- 响应式状态管理器
状态管理 Get 并不是比任何其他状态管理器更好或更差,而是说你应该分析这些要点以及下面的要点来选择只用 Get,还是与其他状态管理器结合使用. Get不是其他状态管理器的敌人,因为Get是一个微框架 ...
- spring-mvc 系列:域对象共享数据
目录 一.使用ServletAPI向request域对象共享数据 二.使用ModelAndView向request域对象共享数据 三.使用Model向request域对象共享数据 四.使用Map向re ...
- 详解GaussDB(DWS)的query_band负载识别与应用
摘要:query_band是一个会话级别(session)的GUC参数,本身是字符串类型,支持任意形式字符组合. 本文分享自华为云社区<GaussDB(DWS)的query_band负载识别与应 ...
- ROMA集成关键技术:增量数据集成
摘要:本文将详解ROMA集成关键技术-增量数据集成技术. 本文分享自华为云社区<ROMA集成关键技术(2)-增量数据集成技术>,作者:华为云PaaS服务小智 . 1.概述 ROMA平台的核 ...
- Solon 问答:项目如何直接添加 https 支持?
app.yml 添加两行配置即可: #设定SSL证书(支持:solon.boot.jdkhttp 或 solon.boot.jlhttp 或 solon.boot.jetty 或 solon.boot ...
- QA: Solon 出现中文乱码怎么办?
有些服务器可能会出现中文乱码,有些又不会.也是挺晕的. 可以用 jvm 启动参数试一下: java -Dfile.encoding=utf-8 -jar demoapp.jar