【问题标题】:casting an enum through a void *通过 void * 投射枚举
【发布时间】:2011-10-05 04:33:16
【问题描述】:

我正在尝试将一些旧的 32 位代码转换为 64 位。我收到的更常见的警告之一是:

警告:指针转换为不同大小的整数

当一个函数调用pthread_create 时会发生这种情况,该函数接受一个 void * 来将数据传递给新线程。调用线程将 void * 放入一个枚举(因此 64 位的大小不匹配)。代码如下:

typedef enum {
zero,
one,
two
}numbers_e;

some_function(...)
{
    numbers_e mydata=zero;

    ...
    pthread_create(..., (void *)mydata);
    ...
}

我设法克服了这个警告:

pthread_create(..., (void *)0 + my_data);

此解决方案非常难看(我正在考虑是否最好将警告保留原样,并在使用它的代码附近加上一个很大的注释)。还有其他解决方案吗?

【问题讨论】:

  • 问题是您将非指针数据作为参数传递给需要指针的函数。您应该按照函数签名的建议传递一个指向数据的指针,并像在函数中适当地访问它一样访问它(如果它是您的代码)。
  • @jeff Mercado:我不是我的代码...
  • 我知道 pthread_create() 函数本身不是您的代码,但您传入的函数应该将参数作为指针访问。一般情况下你应该做的事情。
  • @Jeff Mercado:我同意这首先是不好的用法。但是:新的线程函数不是我要更改的。

标签: c casting pthreads 32bit-64bit porting


【解决方案1】:

您的解决方案不仅丑陋,而且是未定义的行为 (UB),可能会在未来给您带来问题:

  • void* 指针上的算术是非标准的,必须是 编译器的扩展
  • 不指向有效对象的指针的算术是UB

要避免第一个,您可以使用(char*)0 + my_data,但这仍然会让您使用第二个。

你能做什么

  • 将您的价值投给uintptr_t。这是一种保证 与void*(如果存在)兼容。它存在于大多数现代 平台。优点是您的代码无法编译 它不存在的平台,明确表明您有 改变一些东西,然后。
  • 使用指向数据的指针。这是真正的解决方案,方法 设计了 pthreads

不过,对于这两种方法,您都必须修改被调用函数的源代码,因此您最好将其更改为第二个,即应采用的方式。

【讨论】:

    【解决方案2】:

    是的,传递对象的地址。

    pthread_create(..., (void *)&mydata);
    

    只要mydata 在某处可用,那应该是安全的edit

    【讨论】:

    • 谢谢,但在将枚举作为参数传递给调用 pthread_create 的函数的情况下,这将不起作用
    • @Dror Cohen 你能发布一个这样的代码示例吗?我认为它应该适用于任何地方:-)
    • 如果调用 pthread_create 的函数的范围在线程实际运行之前结束 -> 那我就干杯(另见@Omry 答案)
    • @Dror Cohen 只要 mydata 在某处仍然可用。如果你不喜欢它,你可以继续产生未定义的行为:-)
    • 可能从代码示例中不清楚,但 mydata 不是静态的。它在调用 pthread_create 的函数中声明
    【解决方案3】:

    将数据作为指针传递并不是一个好主意,但如果有很多代码可以做到这一点 - 就让它保持原样。 否则,我会按照 cnicutar 的建议传递地址。 请记住,如果 mydata 范围在线程开始之前结束,您可能会遇到损坏问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多