繁体   English   中英

如何安全地将void *强制转换为C中的int?

[英]How do I safely cast a void* to an int in C?

也许,我不应该投。 这是我在做什么:

我正在写一段代码,将Linux设备驱动程序链接到更高级别的库。 库的作者使用void * (通过typedef以新名称)将句柄存储到描述通信通道的特定于实现的对象。

我想与该库连接的驱动程序使用int来存储其通道的句柄(因为它们是open()调用返回的文件描述符)。 因此,在我的代码中,我从库传递了void * ,并且需要使用int从驱动程序中调用东西,反之亦然。 即:

// somewhere in the library ...
typedef void* CAN_HANDLE;

// ... in my code
CAN_HANDLE canOpen_driver(s_BOARD *board)
{
  int fd;
  // ...
  fd = open(busname, O_RDWR);
  // ...
  return (CAN_HANDLE) fd; // <-- not safe, especially not when converting back.
}

其他人编写的适配器实际上将某些struct等存储在某个位置,并且仅在指针之间进行转换,因此不会出现大小问题。 就我而言,我真的不想像操作系统那样管理文件描述符。

在我的PC上,我认为指针大于int ,所以我可以稍微修改一下一下,但代码也进入嵌入式系统,而且我没有足够的经验来假设大小这些机器上的类型。

编辑:当然,您不需要结构,您可以只为一个简单的int分配内存。

CAN_HANDLE canOpen_driver(s_BOARD *board)
{
  int *fd = malloc(sizeof(int));
  if (fd)
  {
    // ...
    *fd = open(busname, O_RDWR);
    // ...
    return (CAN_HANDLE) fd;
  } 

  // failure
  return NULL;
}

假设存在一个匹配的清理呼叫。 就像是:

void canClose_driver(CAN_HANDLE handle)
{
  int *fd = handle;
  free(fd);
}

根据体系结构,您可能会摆脱它。 如果我正确理解,驱动程序将不会真正使用您提供给它的void *。 它只是存储它,以便稍后将其传递回您的代码。

基于该假设,只要sizeof(void *)> = sizeof(int),就可以在这些类型之间进行强制转换,因为您可以确定它确实是一个int。

如果您不能保证大小条件,或者不想依靠黑客,则应该为int分配内存并返回该内存的地址。 例如,您可以使用malloc()或在固定大小的数组中分配int。 缺点是,当不再需要该内存时,您将需要释放该内存。 我想象驱动程序有某种通知,可以在不再需要数据结构时向您的代码发出信号。

通常,在嵌入式系统上,以下CPU模型是最常见的:

Data bus   Address bus   

 8 bit     16 bit  
 8 bit     16+8 bit (banking) 
16 bit     16 bit 
16 bit     16+8 bit (banking) 
32 bit     32 bit

通常,地址总线将始终大于数据总线。 我想不出任何CPU的数据总线会比地址总线大。

这是一个有点肮脏的技巧,可能会也可能不会解决问题:

typedef union
{
  CAN_HANDLE  handle;
  long        value;

} CAN_HANDLE_t;

即使您可能必须使此联合适用于特定系统(远指针等),这也应该相当可移植。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM