当前位置: 首页 > article >正文

不定参数.

不定参数

  • 一、不定参宏函数
    • 1、__ FILE__和__LINE__
    • 2、__ VA_ARGS __
    • 3、示例
  • 二、C风格不定参函数
    • 1、函数(宏)
    • 2、介绍
    • 3、示例
    • 4、vasprintf
      • (1)函数
      • (2)介绍
      • (3)示例
  • 三、C++
    • 1、介绍
    • 2、示例

一、不定参宏函数

1、__ FILE__和__LINE__

  • 在C和C++编程语言中,__FILE__和__LINE__是两个预定义的宏,它们在编译时由预处理器自动替换为当前源代码文件的文件名和当前行号。这两个宏在调试和日志记录中非常有用,因为它们能够帮助开发者快速定位到代码中的具体位置。
  • __FILE__和__LINE__是由预处理器自动处理的,因此它们不需要(也不能)被显式地定义。这两个宏在编译时就已经确定了它们的值,因此它们不能用于运行时动态地获取文件名和行号
功能
__ FILE __代表当前源代码文件的文件名(包括路径,如果编译器提供了路径信息)
__ LINE __代表当前源代码文件中的行号

2、__ VA_ARGS __

  • __VA_ARGS__是一个预处理器宏,它用于在宏定义中处理可变数量的参数。这个特性是在C99标准中引入的,它允许宏接受一个可变数量的参数,并在宏展开时使用这些参数。
  • 当定义一个带有可变参数的宏时,可以在参数列表的末尾使用省略号 … 来表示额外的参数。然后,在宏的定义体中,可以使用__VA_ARGS__来引用这些额外的参数。
  • 需要注意的是,由于宏是在预处理阶段进行文本替换的,因此传递给__VA_ARGS__的参数必须能够直接用于替换位置。如果参数包含逗号,它们仍然会被视为单个参数的一部分,因为逗号是在宏展开后才被解析为参数分隔符的。
// 定义一个宏,打印可变数量的参数
#define PRINT_PARAMS(...) printf(__VA_ARGS__)

int main() {
    // 使用宏打印多个参数
    PRINT_PARAMS("Hello, %s! You have %d new messages.\n", "Alice", 5);
    return 0;
}

3、示例

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

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

int main()
{
    LOG("%s-%d\n", "snowdragon", 8888);
    LOG("\n");
    return 0;
}
gcc args.c

在这里插入图片描述

  • __ VA_ARGS__前不加##,当“没有”传递参数进去时,会报错,报错如下

在这里插入图片描述

二、C风格不定参函数

1、函数(宏)

在这里插入图片描述

2、介绍

  • 在C语言中,处理可变参数列表(variadic arguments)时,通常会用到<stdarg.h>头文件中的几个宏,即va_start、va_arg、va_end以及vasprintf(尽管vasprintf并不是直接处理可变参数列表的宏,而是与之相关的一个函数)。这些宏和函数允许函数接受一个可变数量的参数,并在函数体内访问这些参数。
功能使用
va_start用于初始化一个va_list类型的变量,这个变量将用于访问可变参数列表需要将va_list变量和最后一个已知的固定参数传递给va_start
va_arg用于从va_list变量中获取下一个参数需要指定参数的类型,va_arg将返回该类型的值,并更新va_list以指向下一个参数
va_end用于清理va_list变量在访问完所有可变参数后,应该调用va_end

3、示例

void MyCPrintNum(int count, ...)
{
    va_list ap;
    va_start(ap, count);
    for(int i = 0; i < count; ++i)
    {
        int num = va_arg(ap, int);
        printf("%d:%d\n", i, num);
    }
    va_end(ap);
    printf("\n");
}

int main()
{
    MyCPrintNum(1, 8888);
    MyCPrintNum(3, 6, 66, 666);
    MyCPrintNum(5, 1, 2, 3, 4, 5);

    return 0;
}

在这里插入图片描述

4、vasprintf

(1)函数

在这里插入图片描述

(2)介绍

  • vasprintf 是一个在 C 语言中用于格式化字符串并将其存储在动态分配的内存中的函数。这个函数是 printf 系列函数的一部分,但与 printf、sprintf 等不同的是,vasprintf 接受一个可变参数列表,这允许它接受不定数量的参数。
参数介绍
strp一个指向字符指针的指针,用于接收指向新分配字符串的指针
fmt一个格式字符串,指定了后续参数如何被格式化和插入到最终的字符串中
ap一个 va_list 类型的变量,它已经被 va_start 宏初始化,用于访问可变参数列表
  • vasprintf 函数根据 fmt 字符串和 ap 指定的可变参数列表来构造一个新的字符串,并将这个字符串的地址存储在 *strp 中。如果成功,vasprintf 返回生成的字符串的长度(不包括终止的空字符)。如果失败,它返回 -1,并且 *strp 的值未定义。
  • 使用 vasprintf 后,应该检查返回值以确保字符串被成功创建,并且在不再需要字符串时,使用 free 函数释放它分配的内存,即strp。

(3)示例

#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

void MyCPrint(const char* format, ...)
{
    va_list ap;
    va_start(ap, format);
    char* res = NULL;
    int ret = vasprintf(&res, format, ap);
    if(ret != -1)
        printf("%d: %s\n", ret, res);
    free(res);
    va_end(ap);
}

int main()
{
    MyCPrint("%s %s,%d", "snowdragon", "writed", 8888);
    return 0;
}

在这里插入图片描述

三、C++

1、介绍

  • 相关内容参见C++11(二)中的可变参数模板

2、示例

#include <iostream>

void MyCppPrint()
{
    std::cout << std::endl;
}

template<typename T, typename ...Args>
void MyCppPrint(T type, Args&&... args)
{
    std::cout << "size: " << sizeof ...(args) << ", " << type << std::endl;
    if(sizeof ...(args) > 0)
        MyCppPrint(std::forward<Args>(args)...);
}

int main()
{
    MyCppPrint("snow");
    std::cout << "\n";
    MyCppPrint("snow", 8888);
    std::cout << "\n";
    MyCppPrint("writed", "by", "snowdragon", 8888, 'S');
    return 0;
}

在这里插入图片描述

本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信
本文只是在编写项目,学习过程中所做的总结,不会涉及过深的概念
创作不易,如果觉得博主写得不错,请点赞、收藏加关注支持一下💕💕💕


http://www.kler.cn/a/536452.html

相关文章:

  • 洛谷题目: P8774 [蓝桥杯 2022 省 A] 爬树的甲壳虫 题解 (本题较简)
  • [论文阅读] Knowledge Fusion of Large Language Models
  • QUIC 与 UDP 关系
  • 【医院绩效管理专题】2.绩效管理:医院发展的核心驱动力
  • 数据结构:顺序表
  • MAC 安装mysql全过程记录
  • 2、k8s的cni网络插件和基本操作命令
  • 极客说|利用 Azure AI Agent Service 创建自定义 VS Code Chat participant
  • Codeforces Round 995 (Div. 3)
  • 使用VSCode接入DeepSeek探索
  • 封装descriptions组件,描述,灵活
  • Ansys Maxwell:磁耦合器 - 扭矩与角度分析
  • 800G光模块:引领未来数据中心与网络通信的新引擎
  • GPT-4使用次数有上限吗?一文了解使用规则
  • WPF 进度条(ProgressBar)示例一
  • 【Pandas】pandas Series skew
  • Nginx SSL: error:1410D0B 错误
  • C#+Redis接收数据并定时3秒钟频率异步保存到数据库
  • [Halcon] 灰度值插值介绍
  • 数据库开发常识(10.6)——考量使用多视图连接、循环删除、绑定变量、连接表数及触发器(2)
  • C++ labmbd表达式
  • 在 Flownex 中创建自定义工作液
  • 寻找2020
  • 【算法】动态规划专题⑥ —— 完全背包问题 python
  • Maven 依赖管理全面解析
  • 【有啥问啥】什么是CTC(Connectionist Temporal Classification)算法