【问题标题】:Type-casting void* to long将 void* 类型转换为 long
【发布时间】:2016-04-10 08:32:25
【问题描述】:

是否可以直接将 void 指针类型转换为 long 而不会造成麻烦?下面是我从代码here中提取的一小段代码sn-p(页面Pthread Joining部分下的示例)。

{
    void *status;
    long t;
    rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
    rc = pthread_join(thread[t], &status);
    printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
}

正如this manual page 所说,pthread_join() 将目标线程的退出状态(即目标线程提供给 pthread_exit() 的值)复制到 *retval(在这种情况下为 *status) 指向的位置.但是在我提到的程序中,状态并不指向任何位置。那么程序如何仍然有效?

其次,据我所知,状态不能保持长值那么类型转换状态如何给我们一个长而不是地址的值?

【问题讨论】:

  • @MartinR :正如this 所说,pthread_join() 将目标线程的退出状态(即目标线程提供给 pthread_exit(3) 的值)复制到该位置由 *retval 指向。但是在我提到的程序中,status 没有指向任何位置,那么该程序是如何工作的?
  • 这是偶然的。变量状态未初始化,因此它将写入状态指向的任何位置。碰巧,它可能在某个地方是合法的。如果它是非法的,你会遇到崩溃。
  • @cup :这是否意味着 turorial 不可靠?他们如何通过将指针类型转换为 long 而不是取消引用来获得正确的输出?
  • 抱歉 - 我之前的评论不正确,因为您没有发布调用 pthread_exit 的代码。在本教程中,pthread_exit 将 long 转换为 void*。 pthread_join 获得 pthread_exit 的结果,因此它必须将其重铸回 long。本教程是可靠的,但它假定 void* 占用的空间至少与 long 相同或更多。

标签: c pthreads pthread-join


【解决方案1】:

快速回答:不,使用 intptr_t

长答案: long 不保证适合空 *。在某些系统(尤其是 64 位 Intel Linux 机器)上,它可以工作,因为 void * 和 long 都是 64 位数量并且 Intel 处理器没有其他类型差异。在其他机器上,比如 32 位 Intel Linux,它不会工作,因为 long 是 64 位的,而 void * 32 位在这些机器上。更多奇特的机器具有不同的属性。

支持 int 指针转换的标准类型是 intptr_t,可在 stdint.h 中找到。根据POSIX 程序员手册

以下类型指定有符号整数类型,其属性是任何指向 void 的有效指针都可以转换为该类型,然后转换回指向 void 的指针,结果将与原始指针进行比较: intptr_t

所以 intptr_t 是一个未指定长度的有符号整数类型,保证支持从 void * 到 void * 的转换。还有未签名的uintptr_t。

Here is the definition of intptr_t in glibc。可以看到,在 64 位机器上 intptr_t 和 long 确实是同一个类型。

【讨论】:

  • 该文档说intptr_t 可以保存任何指针的值,反之亦然。例如,如果指针是 32 位的,intptr_t 是 64 位的,就可以满足要求。 (也就是说,从指针到整数并返回的转换会起作用。)我认为没有任何类型可以保证具有相反的属性。
  • 这是一个很好的观点,尽管阅读 glibc 源代码我相信它实际上可以与该特定实现一起使用。但我同意标准没有要求。随时编辑我的答案以澄清。
【解决方案2】:

这一行:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);

不正确。

建议使用:

rc = pthread_create(&thread[t], &attr, BusyWork, (void *)&t);

那么“问题”就消失了

注意:在Busywork() 函数中通过以下方式获取实际值:

long myVar = *parmVoidPtr;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 2022-01-06
    相关资源
    最近更新 更多