关于“指针值用于预期浮点型位置”编译报错的代码疑问
编译错误分析:"pointer value used where a floating-point was expected"
我对以下编译错误感到困惑,不清楚错误中的“floating-point”来源:
error: pointer value used where a floating-point was expected
279 | ret_value = (void *)((IntFuncWithThreeArg)closure->bound_func)((int)args_values[0], (double)args_values[1], (int)args_values[2]);
这段代码是调用一个返回int类型的FFI闭包,类型定义如下:
typedef int (*IntFuncWithThreeArg)(int, double, int);
其中ret_value是void*类型,args_values是存储不同类型数据的void*数组。想知道是这段代码的问题,还是其他位置出错?
补充代码
闭包绑定相关代码
typedef void (*GeneralFunc)(); typedef struct { char *name; char *ret_t; char **args_t; uint8_t args_n; void *bound_func; } ClosureBinding; ClosureBinding *bind_closure(char *ret_t, char *name, GeneralFunc closure_p, char *args_t[], const uint8_t args_n, void *stream) { ffi_cif cif; ffi_type *args[args_n]; ffi_closure *closure; void *bound_func; _Bool failed; failed = 1; closure = NULL; closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_func); if (closure) { for (uint8_t i = 0; i < args_n; ++i) args[i] = strcmp(args_t[i], "int") == 0 ? &ffi_type_sint : strcmp(args_t[i], "double") == 0 ? &ffi_type_double : &ffi_type_schar; if (ffi_prep_cif(&cif, ABI, args_n, strcmp(ret_t, "int") == 0 ? &ffi_type_sint : strcmp(ret_t, "double") == 0 ? &ffi_type_double : &ffi_type_schar, args) == FFI_OK) if (ffi_prep_closure_loc(closure, &cif, closure_p, stream, bound_func) == FFI_OK) failed = 0; } return new_closure_binding(name, ret_t, args_t, args_n, bound_func); } [...] typedef struct Object_t { ClosureBinding **closures; uint8_t closures_n; void *(*call)(struct Object_t *self, int index, ...); } Object; void *call(Object *self, int index, ...); Object *new_object(const uint8_t closures_n) { Object *self = (Object *)malloc(sizeof(Object)); self->call = call; self->closures = malloc(sizeof(ClosureBinding) *closures_n); self->closures_n = closures_n; return self; }
关键的call函数实现
typedef int (*IntFuncWithThreeArg)(int, double, int); void *call(Object *self, int index, ...) { va_list args; va_start(args, index); ClosureBinding *closure = self->closures[index]; printf("Call the '%s' closure\n", closure->name); // Get the closure argument values from variadic arguments void *args_values[closure->args_n]; for (int i = 0; i < closure->args_n; ++i) { char *arg; printf("Before argument allocation\n"); arg = closure->args_t[i]; if (!strcmp(arg, "int")) { int *p = malloc(sizeof(int)); *p = va_arg(args, int); args_values[i] = p; } else if (!strcmp(arg, "double") || !strcmp(arg, "float")) { double *p = malloc(sizeof(double)); *p = va_arg(args, double); args_values[i] = p; } } void *ret_value; if (!strcmp(closure->ret_t, "int")) { if (closure->args_n == 3) { ret_value = (void *)((IntFuncWithThreeArg)closure->bound_func)(*(int *)args_values[0], *(double *)args_values[1], *(int *)args_values[2]); } else { ret_value = (void *)-1; fprintf(stderr, "Warning: Attempt to execute an INT type closure but argument's type is unregistered\n"); } } else { ret_value = (void *)-1; fprintf(stderr, "Warning: Return type unregistered\n"); } va_end(args); return ret_value; }
问题原因与修复
错误根源
- 参数传递非法转换:原始错误代码中
(double)args_values[1]是直接把void*指针值转换为double,而非取出指针指向的double实际值。编译器检测到将指针当作浮点数使用的非法操作,因此抛出错误。 - 返回值转换优先级(非核心,但需注意):
(void *)的转换优先级低于函数调用,原代码实际是先调用函数得到int返回值再转成void*,这部分本身合法,但参数错误是核心问题。
修复代码
修正call函数中的闭包调用逻辑:
if (!strcmp(closure->ret_t, "int")) { if (closure->args_n == 3) { // 先取出指针指向的实际值,传递给闭包 int result = ((IntFuncWithThreeArg)closure->bound_func)( *(int *)args_values[0], *(double *)args_values[1], *(int *)args_values[2] ); // 用intptr_t中转,保证跨平台指针转换的安全性 ret_value = (void *)(intptr_t)result; } else { ret_value = (void *)-1; fprintf(stderr, "Warning: Attempt to execute an INT type closure but argument's type is unregistered\n"); } }
额外注意点
- 代码中
args_values数组内的malloc分配内存未释放,需在函数返回前添加循环释放逻辑,避免内存泄漏。 - 引入
<stdint.h>头文件以使用intptr_t类型,确保int转void*的可移植性。
内容的提问来源于stack exchange,提问作者siery
相关产品推荐
相关产品推荐

