You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于“指针值用于预期浮点型位置”编译报错的代码疑问

编译错误分析:"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;
}

问题原因与修复

错误根源

  1. 参数传递非法转换:原始错误代码中(double)args_values[1]是直接把void*指针值转换为double,而非取出指针指向的double实际值。编译器检测到将指针当作浮点数使用的非法操作,因此抛出错误。
  2. 返回值转换优先级(非核心,但需注意):(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:33:19