C++项目实战——基于多设计模式下的同步&异步日志系统-②-前置知识补充-不定参函数

文章目录

专栏导读

🌸作者简介:花想云,在读本科生一枚,C/C++领域新星创作者,新星计划导师,阿里云专家博主,CSDN内容合伙人...致力于 C/C++、Linux 学习。

🌸专栏简介:本文收录于 C++项目------基于多设计模式下的同步与异步日志系统

🌸相关专栏推荐:C语言初阶系列C语言进阶系列C++系列数据结构与算法Linux

不定参函数

C语言中的不定参数函数是一种特殊类型的函数,它允许你定义一个函数,可以接受不定数量的参数。这些函数通常用于处理不确定数量的输入,例如printfscanf等标准库函数,它们可以接受不同数量和类型的参数。

不定参函数的声明格式如下:

c 复制代码
	return_type func_name (format_string, ...);
  • return_type为函数返回值类型;
  • func_name为函数名;
  • format_string是一个格式化字符串,用于指定参数的数量和类型;
  • ... 表示不定数量的参数;

在函数内部我们可以用一些宏或函数来对不定参数进行分解,常见的宏有va_startva_argva_end

c 复制代码
    void va_start(va_list ap, last);
    type va_arg(va_list ap, type);
    void va_end(va_list ap);
  • va_list:va_list是一个类型,用于声明一个参数列表的对象,它的本质其实是void*;
  • va_start:用于初始化va_list对象,使其指向不定参数列表的第一个参数;
  • va_arg:用于获取不定参数列表中的参数;
  • va_end:用于清空可变参数列表;

示例1

c 复制代码
#include <stdio.h>
#include <stdarg.h>

void printNum(int count, ...)
{
    va_list ap;
    va_start(ap, count); // 初始化ap指针,使其指向不定参数列表的第一个参数
    for(int i = 0; i < count; i++)
    {
        int num = va_arg(ap, int); // 从不定参数列表中抽取int类型的参数
        printf("%d ", num);
    }
    printf("\n");
    va_end(ap); // 将ap置空
}

int main()
{
    printNum(5, 1, 2, 3, 4, 5);
    return 0;
}

示例2

c 复制代码
#define _GNU_SOURCE

#include <stdio.h>
#include <stdarg.h>

void myprintf(const char* format, ...)
{
    va_list ap;
    va_start(ap, format);
    char* res;
    int ret = vasprintf(&res, format, ap);
    if(ret != -1)
    {
        printf(res);
        free(res); // res指向动态开辟的空间,需要手动释放
    }
    va_end(ap);
}
int main()
{
    myprintf("%s-%d\n", "huaxiangyun", 100);
    return 0;
}

注意

示例中vasprintf 是一个 C 库函数,它可以通过可变参数创建一个格式化的字符串,并将其存储在动态分配的内存中。它的使用方法与 printf类似,但它不会将结果打印到标准输出流中,而是将其存储在一个指向字符数组的指针中

函数原型如下:

cpp 复制代码
#include <stdarg.h>
#include <stdio.h>

int vasprintf(char **str, const char *format, va_list ap);

C++风格不定参函数

在C++中,有两种主要方式来创建不定参数函数:

  • C风格的不定参数函数:这种方式与C语言中的不定参数函数类似,使用了C标准库中的va_list、va_start、va_arg和va_end宏。这种方式在C++中仍然有效,但不够类型安全,不太推荐在现代C++代码中使用。

  • C++11引入的可变参数模板:这是更现代和类型安全的方式,使用了C++的模板和新的语法特性。可变参数模板允许你定义一个接受不定数量参数的函数,并且能够在编译时进行类型检查。这种方式更灵活,并且是C++推荐的方式。

示例3

cpp 复制代码
#include <iostream>

// 无参特化
void xprintf()
{
    std::cout << std::endl;
}

template <typename T, typename ...Args>
void xprintf(const T &v, Args &&...args)
{
    std::cout << v;
    if((sizeof ...(args)) > 0)
    {
        xprintf(std::forward<Args>(args)...); // 递归分解参数包
    }
    else
    {
        xprintf();
    }
}

int main()
{
    xprintf("huaxinagyun");
    xprintf("aaaa", 1000);
    return 0;
}

不定参宏函数

示例4

c 复制代码
#include <stdio.h>

#define LOG(format, ...) /
	printf("[%s : %d]\n", format, __FILE__, __LINE__, ##__VA_ARGS__)

int main()
{
    LOG("日志消息");
    return 0;
}
相关推荐
螺旋天光极锐斩空闪壹式!1 分钟前
自制游戏:监狱逃亡
c++·游戏
Thomas_Cai2 分钟前
Python后端flask框架接收zip压缩包方法
开发语言·python·flask
霍先生的虚拟宇宙网络4 分钟前
webp 网页如何录屏?
开发语言·前端·javascript
温吞-ing6 分钟前
第十章JavaScript的应用
开发语言·javascript·ecmascript
魔道不误砍柴功12 分钟前
实际开发中的协变与逆变案例:数据处理流水线
java·开发语言
鲤籽鲲20 分钟前
C# MethodTimer.Fody 使用详解
开发语言·c#·mfc
亚图跨际24 分钟前
Python和R荧光分光光度法
开发语言·python·r语言·荧光分光光度法
Rverdoser32 分钟前
RabbitMQ的基本概念和入门
开发语言·后端·ruby
dj244294570735 分钟前
JAVA中的Lamda表达式
java·开发语言
工业3D_大熊1 小时前
3D可视化引擎HOOPS Luminate场景图详解:形状的创建、销毁与管理
java·c++·3d·docker·c#·制造·数据可视化