51

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 {
};

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. Any explanations, ideas? Anyone seen this before (I'm sure some of you have :).

Thanks! :bp:

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Billy Pilgrim
  • 1,842
  • 3
  • 22
  • 32
  • Memory Allocation declaration – Jebathon Jul 10 '14 at 20:13
  • 13
    I'm not sure what it's supposed to mean, but it's non-standard; the syntax for a struct declaration requires at least one member. Perhaps it's a placeholder for future expansion? – Keith Thompson Jul 10 '14 at 20:15
  • It doesn't appear to allocate anything... – Billy Pilgrim Jul 10 '14 at 20:15
  • 2
    [Normally, it's not an empty struct](https://www.kernel.org/doc/htmldocs/device-drivers/API-struct-device.html)... As for *why* this was done in this instance, it's hard to say without more context. – Cornstalks Jul 10 '14 at 20:30
  • One possibility is there used to be a member in the struct "device", someone deleted that member because it was no longer required and forgot to delete the struct or didn't delete it because it required more code changes. – Étienne Jul 10 '14 at 21:15
  • Maybe a part of this. [Chapter 9. Serial Peripheral Interface (SPI)](https://www.kernel.org/doc/htmldocs/device-drivers/spi.html) See spi_alloc_master, struct spi_master etc. – Toris Jul 11 '14 at 02:55
  • @BillyPilgrim if you feel that one of the posted answers actually answers your question, could you accept it? – ouah Jan 02 '15 at 19:17

5 Answers5

44

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

ouah
  • 142,963
  • 15
  • 272
  • 331
  • There would be a problem forwarding declarations in the code sent by the OP: struct spi_device is defined (rather than declared), so the compiler must know how much to allocate for it. – rslemos Jul 10 '14 at 20:29
  • @ouah I think we're all scratching our heads on why the hell such a definition is ever done. I apologize for my text; re-reading it now, it feels like I was criticizing your answer. Sorry, I was not. – rslemos Jul 10 '14 at 20:34
  • 2
    A problem with empty structures is if they also have `sizeof` being `0` then an array of them violates the rule that different objects must have different addresses. For example, what happens with `struct device d[20], *ptr; for (ptr = d; ptr < d + 20; ++ptr)` ? – M.M Jul 10 '14 at 23:26
  • @MattMcNabb - the link to gcc.gnu.org says "G++ treats empty structures as if they had a single member of type char", so I doubt `sizeof` would ever equal `0` – cegfault Jul 11 '14 at 06:22
  • @cegfault We're talking about `gcc`, not `g++` – M.M Jul 11 '14 at 06:37
  • 2
    @cegfault: `g++` compiles C++, and the rules for this are different in C++ (another example of why "C/C++" questions are to be avoided!) – Lightness Races in Orbit Jul 11 '14 at 09:19
22

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.

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
3

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.

Dreamer
  • 1,139
  • 9
  • 18
  • 2
    Sounds like you are talking about opaque structs - that is, one that was declared but not defined, as in `struct device;`. But the question shows something different: the struct has been defined to be empty. – hmijail Dec 13 '16 at 15:59
2

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

1

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

J M D
  • 127
  • 3