You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义printf中<stdarg.h>的va_args无法正常遍历参数问题

问题原因

你遇到的问题核心是va_list的传递方式错误:
C语言中va_list作为函数参数传递时是值传递,你在get_args里调用va_arg移动的是va_list的副本指针,而ft_printf里的原始va_list args完全没变化。所以第二次处理%c时,还是从初始位置取参数,拿到的依然是第一个's'。

修复方案

把get_args的参数改成va_list的指针(传递原始va_list的地址),这样函数内部操作的是原始的va_list对象,每次va_arg都会让指针正确前进,就能依次读取所有可变参数了。

修改后的完整代码

#include <stdarg.h>
#include <unistd.h>

// 补充你省略的print_char实现
static int print_char(int c)
{
    return write(1, &c, 1);
}

// 修改参数为va_list指针
static int get_args(va_list *args, char format)
{
    if(format == 'c')
        return print_char(va_arg(*args, int)); // 解引用指针操作原始va_list
    // 可扩展其他格式处理,默认返回0
    return 0;
}

int ft_printf(const char *format, ...)
{
    va_list args;
    int i;
    int len;
    
    len = 0;
    i = 0;
    
    va_start(args, format);
    while (format[i])
    {
        if (format[i] == '%')
        {
            // 传递args的地址给get_args
            len += get_args(&args, format[i + 1]);
            i++;
        }
        else
        {
            write(1, &format[i], 1);
            len++;
        }
        i++;
    }
    va_end(args);
    return len;
}

int main()
{
    printf("Characters: %c %c \n",'s','e');
    ft_printf("Characters: %c %c\n",'s','e');
    
    return 0;
}
关键说明

va_list本质是封装后的指针类型(不同编译器实现细节有差异,但值传递特性一致)。如果传值给函数,函数内部得到的是独立副本,对副本的指针移动不会影响原始va_list的状态,导致后续读取参数始终停留在第一个参数位置。改用指针传递后,函数内部直接操作原始va_list,每次va_arg都会让指针正确移动到下一个参数位置,就能得到预期输出。

内容的提问来源于stack exchange,提问作者Negar Nasiri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:27:33