1

While going through PCIe driver, I see this type of struct array initialization

static struct pci_device_id DWC_ETH_QOS_id[] = {
    { PCI_DEVICE(VENDOR_ID, DEVICE_ID), },
    { },
}

I found similar code in device tree of_device_id initializer as well:

static const struct of_device_id rh850_match_table[] = {
    { .compatible = "renesas,rh850" },
    { }
};

Why is there an empty {} at the end?

Thanks for the help!

MG47
  • 55
  • 1
  • 8
  • 5
    Presumably other code takes a pointer to the array without knowing its size, and needs an empty sentinel element at the end in order to know when it must stop reading. Chances are that reading code that uses these would show that. – underscore_d Oct 13 '18 at 19:04
  • I see your point: https://elixir.bootlin.com/linux/v4.14.76/source/drivers/of/base.c#L997 – MG47 Oct 14 '18 at 00:13

2 Answers2

3

As @underscore_d pointed out, {} is added as a sentinel element so that the code that loops over these arrays knows when to stop. It relies on the last 'empty' sentinel element as the termination condition.

The code that relies on the sentinel element:

struct of_device_id table: https://elixir.bootlin.com/linux/v4.14.76/source/drivers/of/base.c#L997

struct pci_device_id: https://elixir.bootlin.com/linux/v2.6.35/source/drivers/pci/pci-driver.c#L246

MG47
  • 55
  • 1
  • 8
2

The ISO C grammar requires an initialiser list to be non-empty, however, some compilers (e.g. GCC) permit this.

Here is a discussion on the topic.

The answer to what happens if its empty (do you get as-if-zero if there is no = {...} part) is "yes if the object has static duration, no if not".

Personally I initialize with values I know and do not depend on undefined behaviour. It could limit code portability but I suspect that is not an issue in the community where this practice is common (Linux drivers where GCC is the default compiler.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
Hogstrom
  • 3,581
  • 2
  • 9
  • 25
  • 1
    Don't the uninitialized elements all get default initialized, which in C means zeroed? – Jonathan Leffler Oct 13 '18 at 19:30
  • 2
    If an initializer doesn't provide values for all elements/members, the remaining elements/members are default initialized, regardless of whether the object is static or not. The standard doesn't provide for `{ }`, but presumably the same rule would apply. – Keith Thompson Oct 13 '18 at 19:36
  • @KeithThompson In case at least one member variable is initialized explicitly then `{}` might hold true for an array member variable? http://port70.net/~nsz/c/c11/n1570.html#6.7.9p21 – Gaurav Oct 13 '18 at 19:48
  • @Observer: Not sure what you're asking. C doesn't specify the semantics of `{}`, but we can make reasonable inferences. – Keith Thompson Oct 13 '18 at 20:35
  • 1
    I don't see any discussion of the empty initialiser in the discussion you linked. Here is a real one: [Is an empty initializer list valid C code?](https://stackoverflow.com/questions/17589533/is-an-empty-initializer-list-valid-c-code) The answer is indeed no. – underscore_d Oct 14 '18 at 00:17
  • OP asked about other aspects of such initializer. – 0andriy Oct 31 '18 at 22:52