使用三元运算符获取可变参数时遇编译错误‘expected specifier-qualifier-list before ‘(’ token’
解析编译错误:
expected specifier-qualifier-list before ‘(’ token 我尝试在call函数里用三元运算符循环获取可变参数,结果编译报错expected specifier-qualifier-list before ‘(’ token,代码如下:
#define ARG_N 3 char *args_types[ARG_N] = {"int", "float", "char"}; void call(...) { va_list args; void *args_values[ARG_N]; va_start(args, NULL); for (int i = 0; i < ARG_N; ++i) { char *arg; arg = args_types[i]; args_values[i] = (void *)va_arg(args, (strcmp(arg, "int") ? int : strcmp(arg, "float") ? float : char)); } va_end(args); } int main(void) { call(6, 55.33, 'c'); return 0; }
我原本以为是结构体未初始化导致的,想知道这个错误在当前场景下的具体含义。
错误的核心原因
这个错误和结构体完全无关,问题出在va_arg的用法逻辑上:
va_arg的第二个参数必须是编译阶段就能确定的类型名,它是给编译器用来计算可变参数在栈上的偏移、正确读取对应数据的依据。- 你这里写的
(strcmp(arg, "int") ? int : ...)是一个运行时表达式——strcmp的结果要等程序运行起来才会确定,编译器根本没法把这个表达式解析成合法的类型说明符。
当编译器看到va_arg(args, (strcmp(...)))时,它本来期待第二个位置是int、float这类明确的类型,结果看到的是一个带括号的表达式开头(,所以就抛出了“在‘(’之前需要类型说明符-限定符列表”的错误——说白了就是编译器没找到它需要的合法类型,反而撞见了表达式的括号。
修正思路
既然va_arg的类型必须编译期确定,不能用运行时的字符串判断动态选类型,你可以换用函数指针表的方式,提前把不同类型的参数读取逻辑写好:
#define ARG_N 3 typedef void (*ArgReader)(va_list, void**); void read_int(va_list args, void** dest) { *dest = malloc(sizeof(int)); *(int*)*dest = va_arg(args, int); } void read_float(va_list args, void** dest) { *dest = malloc(sizeof(float)); *(float*)*dest = va_arg(args, float); } void read_char(va_list args, void** dest) { *dest = malloc(sizeof(char)); *(char*)*dest = va_arg(args, char); } // 类型和读取函数的对应表 ArgReader readers[ARG_N] = {read_int, read_float, read_char}; void call(...) { va_list args; void *args_values[ARG_N]; va_start(args, NULL); for (int i = 0; i < ARG_N; ++i) { readers[i](args, &args_values[i]); } // 记得用完后释放内存 for (int i = 0; i < ARG_N; ++i) { free(args_values[i]); } va_end(args); } int main(void) { call(6, 55.33, 'c'); return 0; }
内容的提问来源于stack exchange,提问作者siery
相关产品推荐
相关产品推荐

