在 C++ 中使用 int 作为 void 指针

Using int as void pointer in C++

有一个 C++ 片段必须使用一些旧的纯 C event_handler 函数。

event_handler 有这个共同的签名:

add_event_handler(event_cb callback, void* user_data)

注:event_cb是函数指针,可能与本题无关

user_data定义为让用户传递一些额外的信息给回调。

现在,我的问题真的很简单,(如何)我可以传递一个简单的数字作为 user_data?

add_event_handler(mycallback, 1); // compilation error

显然,因为 1 不是 void*,但是,我怎样才能从堆栈(而不是堆)传递一些简单的变量?

例如:下面的代码是否正确?

int param=1;
add_event_handler(mycallback, &param);

因为这是可行的,但如果我必须注册更多的处理程序,会看起来很丑陋:

int param1=1;
int param2=2;
...
add_event_handler(mycallback, &param1);
add_event_handler(mycallback, &param2);

我只想为一堆事件定义相同的回调并给它们一个整数或枚举值作为 user_data 来决定在 我的回调.

这里是 mycallback:

static void mycallback(void* user_data) {
  // do an action based on user_data, ie: if 1 passed, print "one", if 2 print "two".
}

请注意:我已经尝试搜索这类内容,但是 void* 主题很大,而且 Google 没那么聪明地理解我的愿望。抱歉,如果这里还有另一个相同主题的问题,我也没有找到。在这种情况下,请 post 它,并将其标记为 duplicate.

有一种约定,您将此类处理程序映射到 C++ classes,如下所示:

  1. user_data指向一个class
  2. 的实例
  3. 回调是此 class
  4. static 方法
  5. 回调将 user_data 转换回 class 指针并使用该指针调用真正的回调方法。

您的 int 值将成为此 class 的单个成员。优点是当你需要另一个值时,你可以在 class.

中添加另一个成员

如果(且仅当)user_data指针未在其他地方使用,您可以使用强制转换来转换sizeof 小于(或等于)sizeof(void*) 的任何整数到 void* 类型。

但是,要完全合规,您不能一步完成转换,必须通过中间转换完成:

add_event_handler(mycallback, reinterpret_cast<void*>(static_cast<intptr_t>(1)));

为了能够使用它,您需要进行相反的转换:

static void mycallback(void* user_data) {
    int value = static_cast<int>(reinterpret_cast<intptr_t>(user_data));
}

像这样的转换通常被认为是不好的,但在某些情况下(比如你所拥有的)它确实是传递纯整数值的唯一可能方式。

[注意在32位系统上32位指针,像long long这样的64位整数类型不能这样传递]


正如您在问题中指出的那样,另一种解决方案是使用单独的变量(或可能动态分配的值)来传递实际指针。