21

The Linux kernel source has a lot of array literals like this:

enum {
  FOO,
  BAR
};

static const char* const names[] = {
  [FOO] = "foo", /* wtf is this? */
  [BAR] = "bar",
};

Here each line explicitly indicates the index within the array of the supplied value instead of relying on ordering.

I don't know the phrase to search for - what is this called? What standard defines it? (Or is it a GNU extension?) Can I do this in C++ or just plain C? Experimenting with gcc, I find with the above in test.c,

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE

these commands return success:

$ gcc -Wall -c test.c
$ gcc -Wall -c --std=c90 test.c
$ gcc -Wall -c --std=gnu90 test.c
$ gcc -Wall -c --std=iso9899:1990 test.c
$ gcc -Wall -c --std=c1x test.c

and these commands fail with various complaints about lambdas and operator=:

$ g++ -Wall -c test.c
$ g++ -Wall -c --std=c++98 test.c
$ g++ -Wall -c --std=gnu++98 test.c
$ g++ -Wall -c --std=c++0x test.c
$ g++ -Wall -c --std=gnu++0x test.c

That suggests this is valid C (in just about any dialect) but not C++. But I'm skeptical. I don't remember seeing this used anywhere but the Linux kernel. I also don't see it described in, for example, this list of constructs valid in C but not C++.

Scott Lamb
  • 2,266
  • 1
  • 19
  • 21
  • 1
    If you add `-pedantic` to your compiler lines, you'll see that it was added in C99. – caf Jul 10 '13 at 21:38

2 Answers2

13

It's part of standard C (C99 and newer), called "designated initialization".

From 6.7.9 Initialization, paragraph 6:

If a designator has the form

[ constant-expression ]

then the current object ... shall have array type and the expression shall be an integer constant expression. If the array is of unknown size, any nonnegative value is valid.

And paragraph 33:

EXAMPLE 9 Arrays can be initialized to correspond to the elements of an enumeration by using designators:

enum { member_one, member_two };
const char *nm[] = {
      [member_two] = "member two",
      [member_one] = "member one",
};

According to answers at this question, C++ doesn't support the same behaviour. Your compiler may provide extensions.

Perhaps more helpful to you (and a direct answer to your question) is the GCC documentation, which says:

In ISO C99 you can give the elements in any order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in C90 mode as well. This extension is not implemented in GNU C++.

Community
  • 1
  • 1
Carl Norum
  • 219,201
  • 40
  • 422
  • 469
12

It's a c99 designation initializer.

Designation initializers allow you initialize an array or a struct in any order. Omitted elements are initialized as if they are static objects.

int bla[16] = {[5] = 42, [9] = 42};

this initializes element bla[5] and bla[9] to 42 and all the remaining elements to 0. The designation is an integer constant expression between [].

enum {
  FOO,
  BAR
};

static const char* const names[] = {
  [FOO] = "foo", /* wtf is this? */
  [BAR] = "bar",
};

Here the designation is an enum constant. This is allowed as an enum constant is considered as an integer constant expression in C.

This feature is a C feature and it is not present in C++.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 2
    @0x499602D2, you might be thinking of a time before this behaviour was standardized, or maybe about range-style initializers, which are a GNU extension. Something like `[ 1 ... 6 ] = 12`. Link: http://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html#Designated-Inits – Carl Norum Jul 10 '13 at 21:26
  • @CarlNorum That *was* what I was thinking about. :) Thanks for the link! – David G Jul 10 '13 at 21:33
  • 3
    I believe that they're generally called *designated* initializers in prose, not *designation* initializers. The C99 spec doesn't refer to them as either, but the GCC docs call them designated initializers. It's the initializer which is designated, not the designation which is initialized. – Adam Rosenfield Jul 10 '13 at 21:34
  • @AdamRosenfield I use this wording because C committee wrote in DR#253: *"The term "designated initializer" is never mentioned in the Standard though it appears in the index and new features section (the Standard uses the term "designation initializer" in the text)."* – ouah Jul 10 '13 at 21:37
  • 1
    @ouah: That comment is wrong, C99 doesn't use the term "designation initializer" in the text, unless it's referring to the grammar specification in §6.7.8/1 which defines an *initializer-list* as one or more of (*designation_opt* *initializer*) -- in this case, both the *designation* and *initializer* are independent structural elements, not a single element called a "designation initializer". – Adam Rosenfield Jul 10 '13 at 22:46