Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using non standard declaration of array in C

Tags:

arrays

c

gcc

I came across the following code which declares char * array in C in a non-standard way:

    /* Message Type description array */ 
    char *msgType[M_LAST_MSG] = 
    {    
       [M_INIT_MSG]     "Init", 
       [M_RESET_MSG]    "Serdes Reset"
    };

M_INIT_MSG, M_RESET_MSG and M_LAST_MSG are enumerations with corresponding values of 0, 1 and 2. According to the formal C documentations, the variables inside this array are string (literals) so what is the purpose of using those enumerations in that manner and is there any documentation to back it up?

Compiled with ARM gcc compiler gcc-arm-none-eabi.

like image 494
izac89 Avatar asked Aug 02 '16 13:08

izac89


People also ask

How do you declare an array in C?

To create an array, define the data type (like int ) and specify the name of the array followed by square brackets []. To insert values to it, use a comma-separated list, inside curly braces: int myNumbers[] = {25, 50, 75, 100};

Can we declare array without size in C?

You can declare an array without a size specifier for the leftmost dimension in multiples cases: as a global variable with extern class storage (the array is defined elsewhere), as a function parameter: int main(int argc, char *argv[]) . In this case the size specified for the leftmost dimension is ignored anyway.

What is array .types of array with declaration?

An "array declaration" names the array and specifies the type of its elements. It can also define the number of elements in the array. A variable with array type is considered a pointer to the type of the array elements.

What is array declaration and initialization in C?

There are two ways to initialize an array. Static array initialization - Initializes all elements of array during its declaration. Dynamic array initialization - The declared array is initialized some time later during execution of program.


2 Answers

This syntax allows you to initialize specific elements of an array by index. You can use either int or enum values to specify which array element to initialize. This way, the values you assign don't need to be consecutive.

If for example you had this:

int x[5] = { [2] 3, [4] 7 };

It would be equivalent to this:

int x[5] = { 0, 0, 3, 0, 7 };

In the above example, the enum values specify that elements 0 and 1 of the array are initialized to "Init" and "Serdes Reset".

From section 6.7.8 of the C99 standard:

18 Each designator list begins its description with the current object associated with the closest surrounding brace pair. Each item in the designator list (in order) specifies a particular member of its current object and changes the current object for the next designator (if any) to be that member. The current object that results at the end of the designator list is the subobject to be initialized by the following initializer.

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",
};

EDIT:

Note that the syntax from the standard includes a = while OP's example does not. The syntax without = is apparently an old syntax supported by GCC. Compiling OP's example gives the following warning:

warning: obsolete use of designated initializer without ‘=’

The GCC documentation states the following:

An alternative syntax for this that has been obsolete since GCC 2.5 but GCC still accepts is to write ‘[index]’ before the element value, with no ‘=’.

like image 112
dbush Avatar answered Sep 22 '22 14:09

dbush


That's a GNU extension. It was standardized in C99 with slightly different syntax, namely an equal sign between the [index] and the value and no way to specify a range of indices. They are called designated initializers.

The C standard shows an example of probably the most widespread use, provide a string description for enums:

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",
};

It even allows nifty stuff like

EXAMPLE 11 Designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood:

struct { int a[3], b; } w[] =
    { [0].a = {1}, [1].a[0] = 2 };
like image 43
a3f Avatar answered Sep 22 '22 14:09

a3f