C/C++不定参函数

ops/2025/1/24 6:31:48/

        在学习C语言的时候,往往使用printf进行打印,其中printf函数就是一个不定参的函数,在这个函数内部可以根据格式化字符串中格式化的字符,分别获取不同的参数进行数据的格式化。这里对这类不定参的使用简要做出小结。

C语言中不定参数

        C语言中需要引入stdarg.h的头文件,使用其中的va_list、va_start、va_arg和va_end。

1.va_list:是一个类型,用于声明一个变量,用该变量来存储不定参数的信息。

2.va_start:用于初始化va_list,让va_list指向不定参数的起始位置,可以接受两个参数,第一个是va_list对象,第二个是用于确定不定参数的起始位置。

3.va_arg:用于获取当前位置的值,在每一次使用以后,会将指针移动到下一个可变参数的位置,可以接受两个参数,一个是va_list,一个是要获取的参数的类型。

4.va_end:用于清理va_list对象,确保在使用完不定参以后正确的释放资源。

补充:vasprintf:动态分配内存来存储格式化之后的字符串,但可以接受可变参数,int vasprintf (char **buf, const char *format, va_list ap),buf分别表示指向char指针的指针,用来存储格式化后的字符串地址。format是一个格式化字符串,包含要打印的文本和格式说明符,ap表示可变参数列表。

vasprintf会根据format字符串和可变参数列表ap的内容动态的分配足够的内存来存储格式化后的字符串,并将地址存储在buf指针中,如果成功,就会返回格式化后的字符串的长度。

#include <iostream>
#include <cstdarg>
void printNum(int n, ...)
{va_list al;     //定义一个变量,后面用来存储不定参数的信息va_start(al, n); // 初始化va_list,让va_list指向不定参数列表的起始位置(让al和不定参产生联系)for (int i = 0; i < n; i++){int num = va_arg(al, int); // 此时al与不定参就产生了绑定,使用va_arg来取出当前位置的参数,取完以后会自动往后移一步std::cout << num << std::endl;}va_end(al); // 清空可变参数列表--其实是将al置空
}
int main()
{printNum(3, 11, 22, 33);printNum(5, 44, 55, 66, 77, 88);return 0;
}
#include <iostream>
#include <cstdarg>
void myprintf(const char *fmt, ...)
{// int vasprintf(char **strp, const char *fmt, va_list ap);char *res;va_list al;     //1.初始化va_start(al, fmt);  //2.绑定,设置起始位置int len = vasprintf(&res, fmt, al); //3.按照fmt格式来打印al中的内容,fmt是用户传入的va_end(al);    //4.结束std::cout << res << std::endl;free(res);
}
int main()
{myprintf("%s-%d", "⼩明", 18);return 0;
}

        可以这样来理解:va_list只是定义了一个变量来存储,是个空壳。当使用va_start以后,会让这个空壳与不定参产生联系,也就可以理解成将不定参的变量都存储在这个空壳里了,此时也就不是空壳了。此时我只需要不断地使用va_arg去从va_list中取出数据即可。使用完毕以后就用va_end关闭。

不定参宏函数

不定参宏函数经常使用__VA_ARGS__来表示不定参

#include <iostream>
#include <cstdarg>
#define LOG(fmt, ...) printf("[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
int main()
{LOG("%s-%s", "hello", "你好");return 0;
}

        可以理解为:定义了一个LOG函数,该函数有不定参,调用该函数相当于调用printf,__FILE__表示文件名,__LINE__表示行号,这两个都是stdio.h头文件中的宏,fmt表示参数fmt,##__VA_ARGS__相当于不定参数...,##是为了处理不带参的情况,可以替换以后再理解。

C++不定参函数

使用基本模版

template<typename ...Args>
void print(Args... args) {}

1.递归获取

#include <iostream>void print() {//递归到最后,参数都消耗光了,需要一个无参的函数来兜底
}template <typename T, typename... Args>
void print(T first, Args... args) {std::cout << "Cur : " << first << " args size : " << sizeof...(args) << std::endl;print(args...);  // 递归使用,每次都可以把第一个参数给消耗掉
}int main() {print("nihao", "hello", 11, 222);return 0;
}

       可以这样来理解:定义了一个模版函数,第一个是类型为T的参数,第二个是不定参数,长度未知。每一次递归调用的时候,不定参中的第一个参数就会传入到first这个位置,这样就相当于不定参的一个参数被消耗掉了。接着不断递归,不定参每递归一次都会少一个参数,直到最后没有参数了。

#include <iostream>
#include <cstdarg>
#include <memory>
#include <functional>
void xprintf()
{std::cout << std::endl;
}
template <typename T, typename... Args>
void xprintf(const T &value, Args &&...args)
{std::cout << value << " ";if ((sizeof...(args)) > 0)  //可以使用sizeof ...(args)的方式来计算不定参的长度{xprintf(std::forward<Args>(args)...);   //将不定参递归传入,不定参的第一个参数就会顶替value位置}else{xprintf();}
}
int main()
{xprintf("hello");xprintf("hello", 666);xprintf("nihao", "hello", 666);return 0;
}


http://www.ppmy.cn/ops/11701.html

相关文章

【Redis 神秘大陆】004 高可用集群

四、Redis 高可用和集群 当你发现这些内容对你有帮助时&#xff0c;为了支持我的工作&#xff0c;不妨给一个免费的⭐Star&#xff0c;这将是对我最大的鼓励&#xff01;感谢你的陪伴与支持&#xff01;一起在技术的路上共同成长吧&#xff01;点击链接&#xff1a;GitHub | G…

Iterator 迭代器

意图 提供一个方法顺序访问一个聚合对象中的各个元素&#xff0c;且不需要暴漏该对象的内部表示。 结构 Iterator&#xff08;迭代器&#xff09;定义访问和遍历元素的接口。ConcreteIterator&#xff08;具体迭代器&#xff09;实现迭代器接口&#xff1b;对该聚合遍历是跟踪…

【笔试强训】牛牛快递

链接&#xff1a;牛牛的快递_牛客题霸_牛客网 (nowcoder.com)https://www.nowcoder.com/practice/41b42e7b3c3547e3acf8e90c41d98270?tpId290&tqId39852&ru/exam/oj描述 牛牛正在寄快递&#xff0c;他了解到快递在 1kg 以内的按起步价 20 元计算&#xff0c;超出部分…

遇到PHP方法 二维数组随机排序shuffle 二维数组筛选搜索array_filter

在做二维数组随机排序的时候&#xff0c;发现shuffle 函数挺好用&#xff0c;就不用在做负载的数组随机排序了&#xff0c;对于二维数组同样可以随机排列 php中的shuffle()函数是一个非常有用的函数&#xff0c;常用于随机重排数组中的元素。这个函数可以在很多开发场景中&…

java多线程-练习

需求 代码 使用Callable 方便返回执行的结果&#xff1a;每个线程的发送礼物的数量礼物清单&#xff1a;共享资源&#xff0c;方便上锁礼物数量&#xff1a;线程变量&#xff0c;每个线程发送礼物的数量 public class SendGiftThread implements Callable<Integer> {// 共…

子比主题7.7开心版全版本,一款优雅的WordPress正版主题推荐

可玩性很高的一款主题&#xff0c;也是本站同款主题&#xff0c;直接免费下载&#xff01;子比主题开心版全版本 不恢复授权&#xff0c;不删除文章&#xff01;不恢复授权&#xff0c;不删除文章&#xff01;不恢复授权&#xff0c;不删除文章&#xff01; 主题已经更新7.7非…

了解以太网环网保护倒换(ERPS)

以太网环网保护交换&#xff08;ERPS&#xff09;有助于实现高可靠性和网络稳定性。本文概述了ERPS&#xff0c;包括其定义、基本概念和优点。 什么是ERPS&#xff1f; 以太网环网保护切换&#xff08;ERPS&#xff09;是一种标准化的网络设计方法&#xff0c;旨在确保以太网…

通过使用XShell工具、Nginx环境实现服务器项目构建与发布

前言&#xff1a; 在信息化和数字化的今天&#xff0c;网站和应用的构建与发布已成为企业发展的重要一环。为了确保项目的顺利上线和稳定运行&#xff0c;选择合适的工具和环境至关重要。本文将详细介绍如何通过XShell工具以及Nginx环境来实现服务器项目的构建与发布&#xff0…