va_start 与 va_end

本文介绍了在C语言中如何使用va_start和va_end宏管理可变参数,包括它们的作用、调用方式以及在函数`print_formatted`和`dump`中的应用。
摘要由CSDN通过智能技术生成

在C语言中,当我们定义一个可变参数的函数时,我们需要一种方法来依次访问每个参数。va_startva_end宏就是用来处理这些可变参数的。

va_start宏的作用是初始化一个va_list类型的变量,这个变量是用来存储和访问可变参数的。va_start应该在函数中对其它参数做任何处理之前调用。要使用va_start宏,你需要两个参数:首先是你定义的va_list类型变量,其次是函数的最后一个非可变参数。你可以把它理解为告诉va_list变量从哪里开始获取可变参数列表。

下面是va_start宏的一个示例:

#include <stdarg.h>

// 假设format是最后一个非可变参数
va_list args;
va_start(args, format);

当你完成了可变参数的处理,并且不再需要va_list类型变量后,你应该使用va_end宏。va_end宏的作用是清理赋予va_list变量的任何资源。虽然在很多实现中,va_end可能仅仅是一个空操作,但它的使用是标准要求的好习惯,可以保证代码的可移植性。

va_end宏是这样使用的:

va_end(args);

它需要va_list类型变量作为参数,并且应该与每一个va_start宏的调用相匹配。

在可变参数的函数中,format并不是一个特定的变量名,它一般代表函数中最后一个固定的参数,用来告诉va_start宏从哪个参数之后开始处理可变参数列表。

理解这个概念可能需要看一个例子。假设我们有一个函数print_formatted,它的第一个参数是一个格式字符串(类似于printf函数中的格式字符串),后面可以跟任意多的参数。这个格式字符串就是我们所说的“最后一个非可变参数”。

例如:

void print_formatted(const char *format, ...) {
  va_list args;
  va_start(args, format); // 这里,format 是最后一个固定参数
  // ...
  va_end(args);
}

在这个例子中,format的角色就是告诉va_start:可变参数开始于format参数之后,因为format是在省略号...之前定义的最后一个参数。这样,当我们在函数内部使用va_list遍历参数时,它会跳过format,从紧随其后的第一个可变参数开始处理。

简而言之,format就是函数签名中,紧邻可变参数省略号...左边的那个参数。这个“格式参数”只是一个占位符,它在不同函数中可以有不同的名字,关键在于它是可变参数之前的最后一个参数。

void dump(void* buf_src, int len, const char *format, ...)
{
    if (buf_src == NULL || len <= 0)
	{
        return;
    }

    va_list args, args_copy;
    va_start(args, format);
    va_copy(args_copy, args);
    int required_len = vsnprintf(NULL, 0, format, args) + 1;
    va_end(args);
    char *str_buf = (char *)malloc(required_len);
    if (str_buf == NULL)
	{
        va_end(args_copy);
        return;
    }
    vsnprintf(str_buf, required_len, format, args_copy);
    va_end(args_copy);

    char *data_buf = (char *)malloc(len * 3);
    if (data_buf == NULL)
	{
        free(str_buf);
        return;
    }
    unsigned char *byte_src = (unsigned char *)buf_src;
    for (int i = 0; i < len; i++) {
        snprintf(&data_buf[3 * i], 4, "%02X ", byte_src[i]);
    }
    data_buf[len * 3 - 1] = '\0';

    printf("%s:%s\n", str_buf, data_buf);
    free(str_buf);
    free(data_buf);
}

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值