通过引用传递结构而不是指向缓冲区的指针的转换问题

Casting problems with passing a struct by reference instead of a pointer to a buffer

我在通过引用传递 struct 时遇到转换错误。将指针传递给缓冲区工作正常。函数getstuff()实际上是去掉无关部分的libusb_claim_interface()。我正在尝试从插入 Linux 机器的 USB 设备取回一大块数据。

数据是这样进来的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 字节之间的任何地方。我可以通过像原始代码中那样简单地传递一个无符号字符数组来 "solve" ,然后这样做将指针复制到 mystruct_t *fruits:

fruits = (mystruct_t *) buffer;

但我真的很想知道发生了什么以及为什么我在转换结构时遇到这么多麻烦。

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

fruits = (mystruct_t *) buffer; 这个叫做 "pointer punning" 并且不安全,不可移植,一般来说是 UB

另一个问题是你没有为 fruits 结构分配内存。

您可以:

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

  mystruct_t *fruits = malloc(sizeof(*fruits));
  /* malloc checks + .... */
  getstuff((unsigned char *)fruits, sizeof(*fruits));