ft_printf实现中va_arg使用异常:多参数场景下重复读取同一参数
嘿,我完全懂你现在的困惑——明明在ft_format里已经用va_arg取出参数了,结果处理多个%c的时候,却一直重复输出第一个参数'a',对吧?咱们来把这个问题掰扯清楚。
问题根源:va_list的传递方式错了
va_list本质上是一个指向可变参数列表的指针(或者封装的结构体,不同编译器实现略有差异),但你现在是把它按值传递给ft_format函数的。这意味着当你调用ft_format(args, format[i])时,传递的是args的一份拷贝——在ft_format里调用va_arg(args, int)只会移动这个拷贝的指针,而ft_printf里的原始va_list根本没动!
所以每次循环到下一个%c时,原始的va_list还是指向第一个参数'a',自然每次读出来的都是同一个值,就出现了lalalala的结果。
你临时解决方案有效的原因
你在ft_format之后手动加了va_arg(args, int),这时候操作的是ft_printf里的原始va_list,把它的指针推进到了下一个参数。下一次调用ft_format时,拷贝的是已经推进后的指针,所以能读到下一个值。但这种方法太别扭了,而且以后扩展其他格式符(比如%s、%d)时,很容易出错。
正确的修正方案
把ft_format的参数改成va_list的指针,这样在函数里操作的就是原始的参数列表指针,调用va_arg时会真正推进主函数里的va_list。
修改后的代码如下:
1. 修正ft_format函数
int ft_format(va_list *args, const char format) { if (format == 'c') // 解引用指针,操作原始的va_list return (ft_putchar(va_arg(*args, int))); return (-1); }
2. 修正ft_printf里的调用
print_length += ft_format(&args, format[i]);
这样修改后,每次ft_format里的va_arg都会直接操作ft_printf中的原始va_list,把指针推进到下一个参数,就能依次读取'a'、'b'、'c'、'd',输出和标准printf一致的lalblcld了。
备注:内容来源于stack exchange,提问作者hanine

