C语言 可变参数列表及相关宏

本文章介绍一下C语言中一些跟可变参数相关的宏及其用法

这里写目录标题

  • 引言
  • va_list
  • va_start
  • va_arg
  • va_end
  • 以上函数的联合使用样例:
  • vsnprintf
  • __VA_ARGS_

引言

C语言中有很多的带有可变参数的函数,例如printf函数,它的定义其实是类似这样子的

void printf(char *format,...);

其中format为格式化的数据,后面三个点是占位符,用来表示可变参数列表
如果我们想自定义带有可变参数的函数的话,format(格式化数据)必须是函数中参数列表的最后一个固定参数,接下来介绍几个跟可变参数列表有关的宏

宏和函数不同,宏在预处理阶段就会被展开,其实现由编译器提供,通常会包含在相应的标准库头文件中。

va_list

#include
va_list args;

va_list数据类型代表可变参数列表,我们可以通过这个数据类型,来使用可变参数列表或者访问可变参数列表中的每一个元素,这个类型一般作为其他函数的参数来使用.

va_start

void va_start(va_list ap, last_arg);

用作初始化可变参数列表
其中 ap 是一个 va_list对象,表示可变参数列表
last_arg 是带有可变参数的函数中的最后一个固定参数

va_arg

type va_arg(va_list ap, type);

用来访问可变参数列表中的某一个参数,并将可变参数列表的指针往后面移动一位

具体的使用例子:

获取可变参数列表中第一个参数,参数类型为int

int num = va_arg(args,int);

获取可变参数列表中第一个参数,参数类型为char *

char *str = va_arg(args,char*);

va_end

void va_end(va_list ap);

结束对可变参数的访问

以上函数的联合使用样例:

void my_printf(char *format, ...) {
    va_list args;
    va_start(args, format); // 初始化可变参数列表

    char *ptr = format;
    while (*ptr != '\0') {
        if (*ptr == '%') {
            ptr++; // 移动到格式字符

            if (*ptr == 'd') {
                int num = va_arg(args, int); // 获取 int 类型参数
                printf("%d", num);
            } else if (*ptr == 's') {
                char *str = va_arg(args, char*); // 获取 char* 类型参数
                printf("%s", str);
            } else {
                printf("Invalid format specifier!"); // 不支持的格式符号
            }
        } else {
            putchar(*ptr); // 普通字符直接输出
        }

        ptr++;
    }

    va_end(args); // 结束可变参数列表
}

vsnprintf

这个是一个函数,而不是一个宏

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

str 指定将格式化数据放入的字符串
size 缓冲区大小
format 格式化数据
ap 可变参数列表

这个函数和snprintf函数非常类似,都是把格式化的数据放入指定长度的字符串中,但是区别是snprintf函数的最后一个参数是三个点的可变参数列表(. . .),而vsnprintf函数的最后一个参数是 va_list类型的可变参数列表

具体使用方式

#include 
#include 

void formatString(char *buffer, size_t size, const char *format, ...) {
    va_list args;
    va_start(args, format);
    
    vsnprintf(buffer, size, format, args);
    
    va_end(args);
}

int main() {
    char buffer[20];
    int num = 42;
    
    formatString(buffer, sizeof(buffer), "The answer is: %d", num);
    
    printf("Buffer content: %s\n", buffer);
    
    return 0;
}

_VA_ARGS

如果我们想在C语言中定义有可变参数的宏的话,就需要使用这个宏

//最简单的定义
#define my_print1(...)  printf(__VA_ARGS__)

//搭配va_list的format使用
#define my_print2(format, ...) printf(format, __VA_ARGS__)  
#define my_print3(format, ...) printf(format, ##__VA_ARGS__)

如果参数列表为空的话,就需要在 __VA_ARGS_前面加上 ##,这样就会去掉前面的逗号,防止编译错误.

#include
#define my_print1(...)  printf(__VA_ARGS__)
int main()
{   
    int a=1,b=2;
    my_print1("%d%d",a,b);
}

你可能感兴趣的:(工作,c语言)