不定参数
一、不定参宏函数 1、__ FILE__和__LINE__ 2、__ VA_ARGS __ 3、示例
二、C风格不定参函数 1、函数(宏) 2、介绍 3、示例 4、vasprintf
三、C++
一、不定参宏函数
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、介绍
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 ;
}
本文到这里就结束了,如有错误或者不清楚的地方欢迎评论或者私信 本文只是在编写项目,学习过程中所做的总结,不会涉及过深的概念 创作不易,如果觉得博主写得不错,请点赞、收藏加关注支持一下💕💕💕