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

Bil*_*rim 47 c struct

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

struct device {
};

struct spi_device {
    struct device dev;
};
Run Code Online (Sandbox Code Playgroud)

它用作:

int spi_write_then_read(struct spi_device *spi, 
const unsigned char *txbuf, unsigned n_tx,
unsigned char *rxbuf, unsigned n_rx);
Run Code Online (Sandbox Code Playgroud)

还在这里:

struct spi_device *spi = phy->spi;
Run Code Online (Sandbox Code Playgroud)

在哪里定义相同.

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

谢谢!:BP:

oua*_*uah 42

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

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

但GNU C扩展:

GCC允许C结构没有成员:

struct empty {
};
Run Code Online (Sandbox Code Playgroud)

结构的大小为零

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

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

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

#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
Run Code Online (Sandbox Code Playgroud)

目的是节省一些空间而不必更改函数API以防万一DEBUG_SPINLOCKS < 1.它还允许定义类型的虚拟(零大小)对象spinlock_t.

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

struct acpi_dev_node {
#ifdef CONFIG_ACPI
    void *handle;
#endif
};
Run Code Online (Sandbox Code Playgroud)

有关最后一个示例,请参阅Greg Kroah-Hartman的讨论:

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

  • 它的目的是什么? (8认同)
  • 空结构的一个问题是,如果它们的`sizeof`为'0`,那么它们的数组违反了不同对象必须具有不同地址的规则.例如,`struct device d [20],*ptr; for(ptr = d; ptr <d + 20; ++ ptr)`? (2认同)
  • @cegfault:`g ++`编译C++,其规则在C++中是不同的(另一个例子,为什么要避免"C/C++"问题!) (2认同)

hac*_*cks 22

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

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

J.2未定义的行为:

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

GCC使用它作为扩展(没有更详细地说明何时/何地应该使用它).在任何程序中使用它将使其特定于编译器.

  • 为了记录,C++明确允许这个(`[C++ 11:9/1]`). (2认同)
  • 是的,我也做了同样的事情.只想注意它:) (2认同)