#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. 华企盾DSC导致导出文件报错常见处理方法

    1.导出文件的进程和打开该文件的进程启用OLE控制是否都是未勾选,以及启用虚拟重定向是否设置一致(要么都勾选要么都不勾) 2.用procmon监控个人模式下导出非加密的文件,搜索writefile的进 ...

  2. 从零玩转设计模式之原型模式-yuanxingmoshi

    title: 从零玩转设计模式之原型模式 date: 2022-12-11 20:05:35.488 updated: 2022-12-23 15:35:44.159 url: https://www ...

  3. Angular 集成 Material UI 后组件显示不正常 踩坑日记

    在使用了 npm 下载 Material 后, 项目不能正常使用 Material 组件, 随后又使用官方命令使用 Material 组件, 仍然不能正常使用 Material 组件. npm 命令 ...

  4. Ubuntu 23.04、22.04、20.04、18.04替换国内源

    Ubuntu配置国内源 配置步骤如下: 1.Ubuntu配置文件位置:/etc/apt/sources.list 2.需要用root权限进入: sudo vi /etc/apt/sources.lis ...

  5. JVM学习-Class文件结构

    文章原文:https://gaoyubo.cn/blogs/844dc0e7.html 一.Class类文件的结构 任何一个Class文件都对应着唯一的一个类或接口的定义信息. 但是反过来说,类或接口 ...

  6. 聊一聊如何整合Microsoft.Extensions.DependencyInjection和Castle.Core(完结篇)

    前言 书接上回,上回我们了解了 castle 代理的一些缺点,本文将开始操作整合 Microsoft.Extension.Dependency和Castle,以让默认的容器可以支持拦截器 我们将以进阶 ...

  7. C#有望成为2023年的编程语言之王

    前言 TIOBE 2023年12月编程语言指数头条新闻:C#有望成为2023年的编程语言之王. TIOBE是什么? 访问地址:https://www.tiobe.com/tiobe-index/ TI ...

  8. DTSE Tech Talk | 第11期:深入浅出畅谈华为云低时延直播技术

    摘要:详解华为云低时延直播在时延.首屏.卡顿率等体验的优化方案,及如何快速接入方法. 本文分享自华为云社区<DTSE Tech Talk | 第11期:深入浅出畅谈华为云低时延直播技术>, ...

  9. 云小课 | 网站接入WAF失败怎么办?看这里就够了

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要: 网站接入WAF失 ...

  10. Intellij idea getter setter 模板设置

    通过getter setter 模板设置 在实体类中 自动添加 @XmlTransient  按 [Alt+Insert],弹出的提示中选择 Getter and Setter Xml Entity ...