C empty struct — what does this mean/do?

后端 未结 5 716
予麋鹿
予麋鹿 2020-12-25 11:04

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:

struct device {
};
         


        
相关标签:
5条回答
  • 2020-12-25 11:27

    This is not C as C structures have to contain at least one named member:

    (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."

    but a GNU C extension:

    GCC permits a C structure to have no members:

    struct empty {
    };
    

    The structure has size zero

    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.

    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):

    #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. It also allows to define dummy (zero-sized) objects of type spinlock_t.

    Another example in the (recent) Linux kernel of an empty structure hack used with conditional compilation in include/linux/device.h:

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

    See the discussion with Greg Kroah-Hartman for this last example here:

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

    0 讨论(0)
  • 2020-12-25 11:27

    This is valid 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

    0 讨论(0)
  • 2020-12-25 11:29

    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.

    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.

    0 讨论(0)
  • 2020-12-25 11:34

    If you add an empty struct as the first member of another struct, the empty struct can serve as a "marker interface", i.e. 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

    0 讨论(0)
  • 2020-12-25 11:39

    This is not standard C.
    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:

    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).

    GCC uses it as an extension (no more detailed is given there about when/where should it be used). Using this in any program will make it compiler specific.

    0 讨论(0)
提交回复
热议问题