通过指针传递可变参数函数时,如何正确传递va_list?
问题分析与解决
你的核心问题是错误地将va_list对象直接传递给了期望接收可变参数(...)的函数。sum函数的第二个参数是...,它需要的是实际的可变参数列表,而不是va_list类型的对象。当你把args_for_func传给sum时,sum内部的va_start会把这个va_list本身当作第一个可变参数,后续读取的都是非法内存,自然得到乱码值。
正确实现方案
要传递预解析的可变参数列表,需要定义一个专门接收va_list的函数(通常命名以v开头,比如vsum),让原有的可变参数函数调用这个函数复用逻辑,同时修改调用者的函数指针类型以匹配这个新函数。
修改后的代码
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> // 专门处理va_list的求和函数 int vsum(size_t n_args, va_list args) { int result = 0; for (size_t i = 0; i < n_args; i++) { result += va_arg(args, int); } return result; } // 原有的可变参数sum函数,内部调用vsum实现 int sum(size_t n_args, ...) { va_list args; va_start(args, n_args); int result = vsum(n_args, args); va_end(args); return result; } // 修改函数指针类型,指向接收va_list的函数 void caller(int (*func)(size_t, va_list), size_t n_args, ...) { va_list args; va_start(args, n_args); va_list args_for_func; va_copy(args_for_func, args); // 打印参数列表 printf("("); for (size_t i = 0; i < n_args-1; i++) { printf("%i, ", va_arg(args, int)); } printf("%i) => ", va_arg(args, int)); // 调用接收va_list的函数 int result = func(n_args, args_for_func); va_end(args_for_func); printf("%i\n", result); va_end(args); } int main() { // 调用时传入vsum而非sum caller(vsum, 5llu, 1, 2, 3, 4, 5); }
关键修改点说明
- 新增
vsum函数:直接接收va_list参数,负责实际的求和逻辑,这是处理预构建可变参数列表的标准方式。 - 调整
sum函数:保留原有的可变参数接口,但内部通过va_start获取参数列表后调用vsum,保证两种调用方式(直接传可变参数、通过va_list)都能复用逻辑。 - 修改
caller的函数指针类型:将函数指针改为int (*func)(size_t, va_list),确保能正确传递va_list对象给目标函数。 - 调用时传入
vsum:让caller调用专门处理va_list的版本,避免类型不匹配问题。
运行这段代码后,就能得到预期输出:(1, 2, 3, 4, 5) => 15
内容的提问来源于stack exchange,提问作者yurich
相关产品推荐
相关产品推荐

