#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++】 变参函数的更多相关文章

  1. C++ 可变参函数实现

    先简单总结一下基本的用法: void sum(int n, ...) { va_list arg_ptr = NULL; //申请一个指针 va_start(arg_ptr, n); //设置指针指向 ...

  2. C/C++中的可变参函数

    可变参函数最好的实例:printf();参数可变 包含的头文件: C语言中:#include<stdarg.h> C++中的可变参的头文件:#include<cstdarg>, ...

  3. C语言变参函数/Variadic fucntion

    几个重要的 宏/类型 定义 Macros Defined in header <stdarg.h> va_start enables access to variadic function ...

  4. Objective-C实现变参函数

    原文:http://www.tanhao.me/pieces/1104.html   NSLog(NSString *format, ...)   + (id)arrayWithObjects:(id ...

  5. C 语言精髓之变参函数

    我们以 printf 这个 very 熟悉的函数为例,来分析一下变参函数.先看下 printf 函数的定义: int printf(const char *fmt, ...) { int i; int ...

  6. java基础---->java中变参函数的使用

    Java的变参函数实现实际上参数是一个数组,今天我们就简单的学习一下它的用法. java中的变参函数 一.它的使用方法如下: public class VariableParam { private ...

  7. 嵌入式C语言自我修养 08:变参函数的格式检查

    8.1 属性声明:format GNU 通过 __atttribute__ 扩展的 format 属性,用来指定变参函数的参数格式检查. 它的使用方法如下: __attribute__(( forma ...

  8. va_start、va_arg、va_end、va_copy 可变参函数

    1.应用与原理         在C语言中,有时我们无法给出一个函数参数的列表,比如: int printf(const char *format, ...); int fprintf(FILE *s ...

  9. Golang教程:函数、变参函数

    函数是完成一个特定任务的代码块.一个函数接受输入,对输入进行一些运算并产生输出. 函数声明 在 Go 中声明一个函数的语法为: func functionname(parametername type ...

  10. C语言变参函数的实现原理

    1. 变参函数简单示例 #include <stdarg.h> #include <stdio.h> int Accumlate(int nr, ...) { ; ; va_l ...

随机推荐

  1. Centos7安装高版本BIND9.16.41(DNS服务器)

    安装高版本BIND9.16.41或9.18.15 双数版本为稳定版如9.16.9.18 使用手册:https://bind9.readthedocs.io/en/v9_16_19/reference. ...

  2. 4种Spring Boot 实现通用 Auth 认证方式

    摘要: 文章介绍了 spring-boot 中实现通用 auth 的四种方式,包括传统 AOP.拦截器.参数解析器和过滤器,并提供了对应的实例代码,最后简单总结了下它们的执行顺序. 本文分享自华为云社 ...

  3. 快来一起玩转LiteOS组件:RHas

    摘要:RHash是一个C语言编写的哈希函数库,用于计算和验证磁力链接和各种消息摘要的控制台实用程序. 本文分享自华为云社区<LiteOS组件尝鲜-玩转RHas>,作者:Lionlace . ...

  4. 2023年iOS App Store上架流程详解(上)

    ​ 很多开发者在开发完iOS APP.进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store ...

  5. 在探索的道路上持续“做对”,火山引擎A/B测试成为这家企业数字基建

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群   最近,乐刻的"百城万店"战略在行业激起了许多讨论.在传统健身馆经营承压.服务业难标准化的语 ...

  6. Spring Boot 整合 Camunda 实现工作流

    工作流是我们开发企业应用几乎必备的一项功能,工作流引擎发展至今已经有非常多的产品.最近正好在接触Camunda,所以来做个简单的入门整合介绍.如果您也刚好在调研或者刚开始计划接入,希望本文对您有所帮助 ...

  7. 42 干货系列从零用Rust编写负载均衡及代理,wmproxy中配置tcp转websocket

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代 ...

  8. 【C++库函数】stringstream-类型转换&&字符分割

    继续填坑٩(•̤̀ᵕ•̤́๑),这次是 stringstream的内容,最初是看到它可以把字符串直接输出成int类型,惊了,但是一直不是很懂.在网上查了很多资料,才终于差不多理解.stringstre ...

  9. SpringCloud Alibaba技术栈(一)微服务介绍

    B 站黑马视频教程:Here 源码-笔记:Code for Github 第一章 微服务总览 1. 软件系统架构的历史 软件系统架构大致经历了:单体应用架构->垂直应用架构->分布式架构- ...

  10. Spring 学习笔记(1)文章导读

    <Spring 学习笔记>系列文章是博主在学习过 Spring 后对其进行总结的入门系列博文,适合初入 Spring 的小白,如果你最近正在学习或者打算学习 Spring 的话,不妨随着本 ...