简体   繁体   English

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

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

Or maybe, I shouldn't cast. 也许,我不应该投。 Here's what I'm doing: 这是我在做什么:

I'm writing a piece of code that links a Linux device driver to a higher level library. 我正在写一段代码,将Linux设备驱动程序链接到更高级别的库。 The authors of the library use void * (under a new name via typedef ) to store handles to an implementation specific object that describes a communication channel. 库的作者使用void * (通过typedef以新名称)将句柄存储到描述通信通道的特定于实现的对象。

The driver I want to connect with the library uses int to store handles to its channels (because they are file descriptors as returned by calls to open() ). 我想与该库连接的驱动程序使用int来存储其通道的句柄(因为它们是open()调用返回的文件描述符)。 So, in my code, I get void * passed in from the library and need to call stuff from the driver using an int and vice versa. 因此,在我的代码中,我从库传递了void * ,并且需要使用int从驱动程序中调用东西,反之亦然。 I. e.: 即:

// 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.
}

The adapters that others have written actually store some struct etc. somewhere and just cast between pointers, so no size issues arise. 其他人编写的适配器实际上将某些struct等存储在某个位置,并且仅在指针之间进行转换,因此不会出现大小问题。 In my case, I don't really want to manage file descriptors, as the OS already does. 就我而言,我真的不想像操作系统那样管理文件描述符。

On my PC, I think the pointer is larger than the int , so I could bit-twiddle my way out of this, but the code goes into embedded systems, too, and I'm not experienced enough to make any assumptions about the size of types on those machines. 在我的PC上,我认为指针大于int ,所以我可以稍微修改一下一下,但代码也进入嵌入式系统,而且我没有足够的经验来假设大小这些机器上的类型。

Edit: Of course you don't need a struct, you can just allocate memory for a plain 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;
}

This assumes there's a matching call to clean up. 假设存在一个匹配的清理呼叫。 Something like: 就像是:

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

Depending on the architecture, you might get away with that. 根据体系结构,您可能会摆脱它。 If I understand correctly, the driver never actually uses the void* that you provide to it. 如果我正确理解,驱动程序将不会真正使用您提供给它的void *。 It simply stores it to pass it back to your code later on. 它只是存储它,以便稍后将其传递回您的代码。

Based on that assumption, as long as sizeof(void*) >= sizeof(int), it will be safe to cast between those types because you are sure that it is really a int. 基于该假设,只要sizeof(void *)> = sizeof(int),就可以在这些类型之间进行强制转换,因为您可以确定它确实是一个int。

If you cannot guarantee the size condition, or do not want to rely on a hack, you should allocate memory for the int and return the address of that memory. 如果您不能保证大小条件,或者不想依靠黑客,则应该为int分配内存并返回该内存的地址。 You might use malloc() or allocate a int in a fixed-size array, for example. 例如,您可以使用malloc()或在固定大小的数组中分配int。 The downside is that you will need to free that memory when it is no longer needed. 缺点是,当不再需要该内存时,您将需要释放该内存。 I imagine that the driver has some kind of notification that signals your code when the data structure is no longer needed. 我想象驱动程序有某种通知,可以在不再需要数据结构时向您的代码发出信号。

Generally on embedded systems, the following CPU models are most common: 通常,在嵌入式系统上,以下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

Generally, the address bus will always be >= than the data bus. 通常,地址总线将始终大于数据总线。 I can't think of any CPU where the data bus would be larger than the address bus. 我想不出任何CPU的数据总线会比地址总线大。

Here's a somewhat dirty trick that may or may not solve the issue: 这是一个有点肮脏的技巧,可能会也可能不会解决问题:

typedef union
{
  CAN_HANDLE  handle;
  long        value;

} CAN_HANDLE_t;

This should be fairly portable, even though you will likely have to adapt this union to the specific system (far pointers etc). 即使您可能必须使此联合适用于特定系统(远指针等),这也应该相当可移植。

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

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