简体   繁体   English

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

[英]C empty struct — what does this mean/do?

I found this code in a header file for a device that I need to use, and although I've been doing C for years, I've never run into this: 我在一个头文件中找到了我需要使用的设备的代码,虽然我已经做了多年的C,但我从来没有遇到过:

struct device {
};

struct spi_device {
    struct device dev;
};

and it used as in: 它用作:

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

and also here: 还在这里:

struct spi_device *spi = phy->spi;

where it is defined the same. 在哪里定义相同。

I'm not sure what the point is with this definition. 我不确定这个定义的重点是什么。 It is in a header file for a linux application of the board, but am baffled by it use. 它位于主板的Linux应用程序的头文件中,但它对它的使用感到困惑。 Any explanations, ideas? 任何解释,想法? Anyone seen this before (I'm sure some of you have :). 之前见过这个的人(我相信你们有些人:)。

Thanks! 谢谢! :bp: :BP:

This is not C as C structures have to contain at least one named member: 这不是C,因为C结构必须包含至少一个命名成员:

(C11, 6.7.2.1 Structure and union specifiers p8) "If the struct-declaration-list does not contain any named members, either directly or via an anonymous structure or anonymous union, the behavior is undefined." (C11,6.7.2.1结构和联合说明符p8)“如果struct-declaration-list不包含任何命名成员,直接或通过匿名结构或匿名联合,则行为是未定义的。”

but a GNU C extension: 但GNU C扩展:

GCC permits a C structure to have no members: GCC允许C结构没有成员:

 struct empty { }; 

The structure has size zero 结构的大小为零

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

I don't know what is the purpose of this construct in your example but in general I think it may be used as a forward declaration of the structure type. 我不知道你的例子中这个构造的目的是什么,但总的来说我认为它可以用作结构类型的前向声明。 Note that in C++ it is allowed to have a class with no member. 请注意,在C ++中,允许有一个没有成员的类。

In Linux 2.4 there is an example of an empty structure type with conditional compilation in the definition of spin_lock_t type alias in Linux kernel 2.4 (in include/linux/spinlock.h): 在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

The purpose is to save some space without having to change the functions API in case DEBUG_SPINLOCKS < 1 . 目的是节省一些空间,而不必在DEBUG_SPINLOCKS < 1情况下更改函数API。 It also allows to define dummy (zero-sized) objects of type spinlock_t . 它还允许定义spinlock_t类型的虚拟(零大小)对象。

Another example in the (recent) Linux kernel of an empty structure hack used with conditional compilation in include/linux/device.h: 另一个(最近的)Linux内核中的另一个例子是在include / linux / device.h中使用条件编译的空结构hack:

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

See the discussion with Greg Kroah-Hartman for this last example here: 有关最后一个示例,请参阅Greg Kroah-Hartman的讨论:

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

This is not standard C. 这不是标准C.
C11: 6.2.5-20: C11:6.2.5-20:

— A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type. - 结构类型描述顺序分配的非空成员对象集(并且在某些情况下,是不完整的数组),每个成员对象具有可选的指定名称和可能不同的类型。

J.2 Undefined behavior: J.2未定义的行为:

The behavior is undefined in the following circumstances: 在以下情况下,行为未定义:
.... ....
A structure or union is defined without any named members (including those specified indirectly via anonymous structures and unions) (6.7.2.1). - 定义的结构或联合没有任何命名成员 (包括通过匿名结构和联合间接指定的成员 )(6.7.2.1)。

GCC uses it as an extension (no more detailed is given there about when/where should it be used). GCC使用它作为扩展 (没有更详细地说明何时/何地应该使用它)。 Using this in any program will make it compiler specific. 在任何程序中使用它将使其特定于编译器。

One reason might to do this for a library is that the library developers do not want you to know or interfere with the internals of these struct. 可能为库执行此操作的一个原因是库开发人员不希望您知道或干扰这些结构的内部。 It these cases they may provide an "interface" version of the structs spi_device/device (which is what you may see) and have a second type definition that defines another version of said structs for use inside the library with the actual members. 在这些情况下,它们可以提供结构spi_device/device的“接口”版本(这是您可能会看到的),并且具有第二类型定义,该定义定义了在库内与实际成员一起使用的所述结构的另一版本。

Since you cannot access struct members or even create compatible structs of that type yourself with that approach (since even your compiler would not know the size actual size of this struct), this only works if the library itself creates the structs, only ever passes you pointers to it, and does not need you to modify any members. 由于您无法使用该方法访问struct成员甚至创建该类型的兼容结构(因为即使您的编译器也不知道此结构的大小实际大小),这只有在库本身创建结构时才有效,指向它的指针,不需要你修改任何成员。

If you add an empty struct as the first member of another struct, the empty struct can serve as a "marker interface", ie when you cast a pointer to that outer struct to a pointer of the inner struct and the cast succeeds you know that the outer struct is "marked" as something. 如果你添加一个空结构作为另一个结构的第一个成员,那么空结构可以作为“标记接口”,即当你将一个指向该外部结构的指针转换为内部结构的指针并且转换成功时你知道外部结构被“标记”为某种东西。

Also it might just be a place holder for future development, not to sure. 它也可能只是未来发展的占有者,不确定。 Hope this helps 希望这可以帮助

This is valid C 这是有效的C.

struct empty;
struct empty *empty;

and facilitates use of addresses of opaque regions of memory. 并且便于使用不透明的存储区域的地址。

Such addresses are usually obtained from and passed to library subroutines. 这些地址通常从库子程序获得并传递给库子程序。

For example, something like this is done in stdio.h 例如,类似这样的东西在stdio.h中完成

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM