C空结构 - 这是什么意思/做什么?

时间:2014-07-10 20:10:52

标签: c struct

我在一个我需要使用的设备的头文件中找到了这个代码,虽然我已经做了多年的C,但我从来没有碰到过这个:

struct device {
};

struct spi_device {
    struct device dev;
};

,用于:

int spi_write_then_read(struct spi_device *spi, 
const unsigned char *txbuf, unsigned n_tx,
unsigned char *rxbuf, unsigned n_rx);

也在这里:

struct spi_device *spi = phy->spi;

它的定义相同。

我不确定这个定义的重点是什么。它位于主板的Linux应用程序的头文件中,但它对它的使用感到困惑。任何解释,想法?之前见过这个的人(我确定你们中的一些人有:)。

谢谢! :沸点:

5 个答案:

答案 0 :(得分:40)

这不是C,因为C结构必须包含至少一个命名成员:

  

(C11,6.7.2.1结构和联合说明符p8)“如果struct-declaration-list不包含任何命名成员,直接或通过匿名结构或匿名联合,则行为未定义。”

但是GNU C扩展名:

  

GCC允许C结构没有成员:

struct empty {
};
     

结构的大小为零

https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html

我不知道你的例子中这个构造的目的是什么,但总的来说我认为它可以用作结构类型的前向声明。注意,在C ++中它是允许的有一个没有成员的班级。

在Linux 2.4中,在Linux内核2.4(在include / linux / spinlock.h中)的spin_lock_t类型别名的定义中有一个带有条件编译的空结构类型的例子:

#if (DEBUG_SPINLOCKS < 1)

/* ... */

typedef struct { } spinlock_t;

#elif (DEBUG_SPINLOCKS < 2)

/* ... */

typedef struct {
    volatile unsigned long lock;
} spinlock_t;

#else /* (DEBUG_SPINLOCKS >= 2) */

/* ... */

typedef struct {
    volatile unsigned long lock;
    volatile unsigned int babble;
    const char *module;
} spinlock_t;

#endif

目的是节省一些空间,而不必在DEBUG_SPINLOCKS < 1的情况下更改函数API。它还允许定义spinlock_t类型的虚拟(零大小)对象。

(最近的)Linux内核中的另一个例子是在include / linux / device.h中使用条件编译的空结构hack:

struct acpi_dev_node {
#ifdef CONFIG_ACPI
    void *handle;
#endif
};

请参阅Greg Kroah-Hartman与最后一个例子的讨论:

https://lkml.org/lkml/2012/11/19/453

答案 1 :(得分:22)

这不是标准C.
C11:6.2.5-20:

  

- 结构类型描述了顺序分配的非空成员对象集(在某些情况下,还有一个不完整的数组),每个对象都有一个可选的指定名称,可能还有不同的类型。

J.2未定义的行为:

  

在以下情况下,行为未定义:
  ....
   - 定义的结构或联合没有任何命名成员(包括那些   通过匿名结构和工会间接指定)(6.7.2.1)。

GCC将其用作extension(不再详细说明何时/何时应该使用它)。在任何程序中使用它都会使编译器具体化。

答案 2 :(得分:3)

库的一个原因可能是库开发人员不希望您知道或干扰这些结构的内部。在这些情况下,它们可以提供结构spi_device/device的“接口”版本(这是您可能看到的),并且具有第二类型定义,该定义定义了在库内与实际成员一起使用的所述结构的另一版本。

由于您无法使用该方法访问struct成员甚至创建该类型的兼容结构(因为即使您的编译器也不知道此结构的大小实际大小),这仅在库本身创建结构时才有效永远传递给你指针,并且不需要你修改任何成员。

答案 3 :(得分:2)

如果添加一个空结构作为另一个结构的第一个成员,则为空 struct可以作为“标记接口”,即当你转换指针时 外结构到内部结构的指针,并且你知道的转换成功 外部结构被“标记”为某种东西。

它也可能只是未来发展的占有者,不确定。希望这有帮助

答案 4 :(得分:0)

这是有效的C

struct empty;
struct empty *empty;

并便于使用不透明的内存区域的地址。

这些地址通常从库子程序中获取并传递给它们。

例如,类似这样的事情在stdio.h中完成