Приведение проблем с передачей структуры по ссылке вместо указателя на буфер

Я получаю ошибки приведения при передаче struct по ссылке. Передача указателя на буфер работает нормально. Функция getstuff() на самом деле является libusb_claim_interface() с удаленными ненужными частями. Я пытаюсь вернуть часть данных с USB-устройства, подключенного к машине с Linux.

Данные приходят в соответствии с этим struct:

typedef struct mystruct {
  unsigned char a;
  unsigned short b;
  unsigned char c;
  unsigned char d;
  ... /* 40 more members of unsigned char */
} mystruct_t;

Однако код, с которым мне дали работать, передает буфер беззнаковых символов. Затем буфер должен установить каждый отдельный член структуры.

Например:

getstuff(unsigned char *data, int length);
void foo(void)
{
  unsigned char apple;
  unsigned short banana;
  unsigned char cherry;
  unsigned char date;
  ...
  unsigned char buffer[44];

  sendstuff(...);
  getstuff(buffer, 44);
  apple = buffer[0];
  banana = buffer[1];
  cherry = buffer[2];
  date = buffer[3];
  ...
}

Вместо этого я хочу фактически определить struct (выше) и передать ссылку на него, а затем получить разумный доступ к членам, например:

getstuff(unsigned char *data, int length);
void foo(void)
{
  unsigned char apple;
  unsigned short banana;
  unsigned char cherry;
  unsigned char date;
  ...
  mystruct_t *fruits;

  sendstuff(...);
  getstuff((unsigned char) fruits, sizeof(mystruct_t));
  apple = fruits->a;
  banana = fruits->b;
  cherry = fruits->c;
  date = fruits->d;
  ...
}

Но это не работает. Сначала я получаю это при компиляции:

warning: cast from pointer to integer of different size [-Wpointer
-to-int-cast]
(unsigned char) fruits,

warning: passing argument 3 of ‘getstuff’ makes pointer from
integer without a cast [-Wint-conversion]

Затем это (которое выбрасывается при разборе libusb.h):

note: expected ‘unsigned char *’ but argument is of type ‘unsigned char’
int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,

Когда я запускаю программу, устройство, кажется, возвращает 21906 байт вместо ожидаемых 44. Если я передаю фрукты в (unsigned char *), программа компилируется без проблем, но затем я получаю от 21900 до 22060 байт. Я мог бы «решить» это, просто передав массив беззнаковых символов, как в исходном коде, но затем сделав это, чтобы скопировать указатель на mystruct_t *fruits:

fruits = (mystruct_t *) buffer;

Но мне бы очень хотелось знать, что происходит и почему у меня так много проблем с созданием структуры.


person Frotz    schedule 10.08.2018    source источник
comment
Вы, вероятно, должны приводить к unsigned char *, а не unsigned char, так как getstuff ожидает unsigned char *. Также похоже, что вам не хватает закрывающей скобки при вызове getstuff. Наконец, пробовали ли вы увидеть, что такое sizeof mystruct_t (распечатав или зарегистрировав его)?   -  person CoffeeTableEspresso    schedule 11.08.2018
comment
После жалоб компилятора я показал, что произошло, когда я привел к unsigned char *. sizeof(mystruct_t) равно 44, как и buffer[].   -  person Frotz    schedule 11.08.2018
comment
откуда вы знаете, что вы возвращаете от 21900 до 22060 байт?   -  person CoffeeTableEspresso    schedule 11.08.2018
comment
Я думаю, что сообщения говорят сами за себя. Вы назначаете переменную char с указателем   -  person 0___________    schedule 11.08.2018
comment
@P__J__ Я думаю, что сообщения тоже говорят сами за себя, но, похоже, у OP все еще есть проблемы.   -  person CoffeeTableEspresso    schedule 11.08.2018
comment
@CoffeeTableEspresso, если да, я написал микроответ   -  person 0___________    schedule 11.08.2018
comment
ссылки - это не то же самое, что указатели, они не выясняют за вас ссылки и разыменования... someval = *somePointer для разыменования, func(&some_value) для передачи по адресу   -  person Grady Player    schedule 11.08.2018
comment
@CoffeeTableEspresso libusb_bulk_transfer() возвращает байты, переданные в качестве ссылки.   -  person Frotz    schedule 11.08.2018
comment
Непонятно, что вы имеете в виду под передачей по ссылке. C не поддерживает ссылки. Это всегда передача по значению. И этот дикий кастинг очень похож на приглашение к неопределенному поведению.   -  person too honest for this site    schedule 11.08.2018
comment
@Frotz: Определенно нет, см. ^   -  person too honest for this site    schedule 11.08.2018
comment
Это не проблема приведения типов, а проблема (де)сериализации. Вы получаете компактный поток данных извне (USB-устройство) и распаковываете его в некую локальную (собственную) структуру. Когда вы смотрите на проблему в этом аспекте, становится очевидным достойное переносимое решение (извлекайте элементы вручную один за другим или найдите что-нибудь на github).   -  person ddbug    schedule 12.08.2018


Ответы (1)


getstuff((unsigned char) fruits, sizeof(mystruct_t)); => getstuff((unsigned char *) fruits, sizeof(*fruits));

fruits = (mystruct_t *) buffer; это называется "каламбур указателя" и небезопасно, не переносимо и вообще UB

другая проблема заключается в том, что вы не выделяете память для структуры фруктов.

Вы можете:

  mystruct_t fruits;
  ....
  getstuff((unsigned char *)&fruits, sizeof(fruits));

or

  mystruct_t *fruits = malloc(sizeof(*fruits));
  /* malloc checks + .... */
  getstuff((unsigned char *)fruits, sizeof(*fruits));
person 0___________    schedule 10.08.2018