C/C++的可变参技术

前言

在C/C++中,可变参函数(Variadic Function)使用省略号…接受不定数量、不定类型的参数,这类函数需要借助<stdarg.h>(C)或者<cstdarg>(C++)中的宏来解析参数。

用法

函数的声明

可变参函数的声明格式为:return_type func_name(fixed_arg,…);

  • fixed_arg:至少需要一个固定参数(用于确定可变参数的起始位置)
  • …:表示后续参数的数量和类型不确定

关键宏

  • va_list:用于声明参数列表变量。
  • va_start(va_list,fixed_arg):初始化参数列表,从fixed_arg之后开始。
  • va_arg(va_list,type):逐个提取参数,需要指定类型type
  • va_end(va_list):清理参数列表

实例:求和函数

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

// 功能:计算不定数量整数的和
int sum(int count, ...) {
    int total = 0;
    va_list args;           // 声明参数列表变量
    va_start(args, count);  // 初始化,从 count 之后开始

    for (int i = 0; i < count; i++) {
        int num = va_arg(args, int);  // 逐个提取 int 类型参数
        total += num;
    }

    va_end(args);  // 清理
    return total;
}

int main() {
    printf("Sum1: %d\n", sum(3, 10, 20, 30));    // 输出 60
    printf("Sum2: %d\n", sum(5, 1, 2, 3, 4, 5)); // 输出 15
    return 0;
}

实例:自定义打印函数

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

void my_printf(const char* format, ...) {
    va_list args;
    va_start(args, format);

    while (*format != '\0') {
        if (*format == '%') {
            format++;  // 跳过 '%'
            switch (*format) {
                case 'd': {
                    int num = va_arg(args, int);
                    printf("%d", num);
                    break;
                }
                case 'f': {
                    double num = va_arg(args, double);
                    printf("%f", num);
                    break;
                }
                case 's': {
                    char* str = va_arg(args, char*);
                    printf("%s", str);
                    break;
                }
                default:
                    putchar(*format);
            }
        } else {
            putchar(*format);
        }
        format++;
    }

    va_end(args);
}

int main() {
    my_printf("Name: %s, Age: %d, Score: %f\n", "Alice", 25, 95.5);
    // 输出:Name: Alice, Age: 25, Score: 95.500000
    return 0;
}

原理

因为函数的传参是从右向左进行传参,栈通常向低地址增长,后压入的参数位于更低的地址,因此就可以根据最后入栈的固定参数依次访问到可变参数。va_list定义为指向参数列表的指针(如char*),根据我们使用va_arg(arg,type)传入的type调整指针指向下一个参数的起始位置,依次获取参数。最后使用va_end进行资源的清理。

使用场景

一般可用于日志输出,参数比较灵活,不确定的函数之中。

如果觉得本文对您有所帮助,可以支持下博主,一分也是缘分😊
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇