Как мне безопасно привести void * к int в C? - PullRequest
0 голосов
/ 07 февраля 2011

Или, может быть, я не должен бросать.Вот что я делаю:

Я пишу фрагмент кода, который связывает драйвер устройства Linux с библиотекой более высокого уровня.Авторы библиотеки используют void * (под новым именем через typedef) для хранения дескрипторов объекта, специфичного для реализации, который описывает канал связи.

Драйвер, который я хочу подключить к библиотеке, использует int для хранения дескрипторов на его каналах (потому что они являются файловыми дескрипторами, возвращаемыми вызовами open()).Итак, в моем коде я получаю 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.
}

Адаптеры, которые написали другие, на самом деле хранят некоторую структуру и т. Д. Где-то и просто приводятся между указателями, поэтому проблем с размером не возникает.В моем случае я не очень хочу управлять файловыми дескрипторами, как это уже делает ОС.

На моем ПК, я думаю, указатель больше, чем int, так что я мог бы немного изменить свойвыход из этого, но код также входит во встроенные системы, и я не достаточно опытен, чтобы делать какие-либо предположения относительно размера типов на этих машинах.

Ответы [ 3 ]

3 голосов
/ 07 февраля 2011

Edit: Конечно, вам не нужна структура, вы можете просто выделить память для простого 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);
}
2 голосов
/ 07 февраля 2011

В зависимости от архитектуры, вам это может сойти с рук.Если я правильно понимаю, драйвер фактически не использует пустоту *, которую вы ему предоставляете.Он просто сохраняет его для последующей передачи обратно в ваш код.

Исходя из этого предположения, до тех пор, пока sizeof (void *)> = sizeof (int) будет безопасно приводить между этими типами, потому чтовы уверены, что это действительно int.

Если вы не можете гарантировать условие размера или не хотите полагаться на хак, вы должны выделить память для int и вернуть адрес этой памяти.Например, вы можете использовать malloc () или выделить int в массиве фиксированного размера.Недостатком является то, что вам нужно будет освободить эту память, когда она больше не нужна.Я полагаю, что у драйвера есть какое-то уведомление, которое сигнализирует о вашем коде, когда структура данных больше не нужна.

0 голосов
/ 07 февраля 2011

Как правило, во встроенных системах наиболее распространены следующие модели процессоров:

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

Как правило, адресная шина всегда будет> =, чем шина данных. Я не могу вспомнить ни одного процессора, в котором шина данных была бы больше, чем адресная шина.

Вот несколько подвох, который может или не может решить проблему:

typedef union
{
  CAN_HANDLE  handle;
  long        value;

} CAN_HANDLE_t;

Это должно быть достаточно переносимо, даже если вам, вероятно, придется адаптировать этот союз к конкретной системе (дальние указатели и т. Д.).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...