自定义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
相关产品推荐
相关产品推荐

