简体   繁体   中英

Evaluation of a statement in C language

struct 
{
    int a[2], b;
} 
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

How to evaluate this line in C language? General declaration of struct is different from this statement. Also accessing of an element in C can be done like [0].a , [0].b like this?

First lines are the definition of a new structure type:

struct {
   int a[2], b;
}

It declares a structure with two members: an array of two int s named a and an int b .

Next can be decomposed as the following, first the variable:

arr[]

which defines a variable arr that is an array of structures. The size of the array is not defined because the variable is initialized (and so its size defined by this initialization) by:

{ [0].a = ... }

This is a new C (C99, which not so new...) syntax to initialize contents of structured data types: designated initializer .

As you are initializing something the context of what you are initializing is defined (array of structure with two members). Then notation [0] just references the first member of the array (so array have at least one element), and as this element is structured [0].a denotes its member a , itself an array. Then this array is initialized too by { 1 } . Here the trick is that the length of this array member is already defined by the type definition: length 2, then { 1 } initializes that array with the first element equals to 1 and the second with 0 (default value for initialization of ints). Etc.

At the end:

{[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

initializes arr as:

  1. an array of length 2
  2. its first element member a initialized to 1,0 and its member b initialized to 1
  3. its second element member a initialized to 2,0, and its member b initialized to 2

If you use assignements then you could have write something like:

struct { ... } arr[2];
arr[0].a[0] = 1;
arr[0].a[1] = 0;
arr[0].b = 1;
arr[1].a[0] = 2;
arr[1].a[1] = 0;
arr[1].b = 2;

Where [0] (for example) denotes the first element of an array but needs to be prefixed with an expression that denotes that array, so arr[0] ...

This is a declaration, not a statement, and that's why what follows the = is an initialiser, not an expression. What you can do in an initialiser is different from what you can do in an expression.

The syntax looks the way it does to resemble the way elements are referenced in expressions. Invalid pseudo-code to explain the meaning:

struct {int a[2], b;} arr[];
arr[0].a = {1};
arr[1].a = {2};
arr[0].b = 1;
arr[1].b = 2;

The array arr is given length 2 because values for two elements are provided. arr[0] is initialised from what would traditionally be written {{1}, 1} . arr[1] is initialised from {{2}, 2} .

Also accessing of an element in C can be done like [0].a , [0].b like this?

TL;DR Only when you're writing a designated initializer .


You have two things here, a structure definition and initialization.

For the initialization part, the designated initializer is used. It takes a form of

 designator: [ constant-expression ] . identifier 

So, in your case,

struct 
{
    int a[2], b;
} 
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

The designated initializer instructs the compiler to create an array arr of two structure elements ( size is determined by the largest index in supplied initializer, Note 1 ) and provides the initial value of the members of those individual elements.

Thus, in your case, the largest index is 1 , so the array arr size is 2 (0-based indexing).

So to speak, [0].a = {1} is trying to initialize the value of member a of element at arr[0] to 1 . This is "equivalent" to arr[0].a[0] . So is for all remaining cases.

Point to note, this is not setting the values of a[0] and a[1] . Here, due to "partial initialization" Note 2 (brace enclosed initializer does not provide initial value of all the members in the array), arr[0].a[0] is set to 1 and arr[0].a[1] is set to 0 .


Note 1:

Quoting C11 , chapter §6.7.9/P22

If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. The array type is completed at the end of its initializer list.

Note 2:

Quoting C11 , chapter §6.7.9/P21 ( emphasis mine )

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate , or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

The first part is defining a struct variable. Normally you see code like this:

// define the type
struct foo { ... };

// define a variable of that type
struct foo x;

But you can combine the two:

// define a type and a variable of that type
struct foo { ... } x;

In the latter case you don't even have to name the type:

// define a variable of an unnamed struct type
struct { ... } x;

In your case we have struct { int a[2], b; } struct { int a[2], b; } , so we're dealing with an unnamed struct with two members, an array of 2 ints called a and an int called b .

The variable we're declaring is arr . The [] after the name mean that we're defining it as an array.

Usually we see something like:

// define an array of 2 elements
int arr[2];

We can add an initializer:

// define and initialize an array of 2 elements
int arr[2] = { 100, 200 };

With an initializer we don't have to say explicitly how big the array is; it follows from the initializer:

// define and initialize an array of 2 elements
int arr[] = { 100, 200 };

Applying this to your case, you might expect to see something like:

struct { int a[2], b; } arr[] = { { {1}, 1 }, { {2}, 2 } };
//                                  ^a^         ^a^
//                                ^^struct^^  ^^struct^^ 

The braces get a bit crazy because we have an array ( int a[2] ) nested inside a struct nested inside an array ( arr[] ). If you're wondering what happened to the second elements of the a s: When a variable is only partially initialized, all remaining parts are set to 0 . So this code really initializes the inner arrays as {1, 0} and {2, 0} .

The initializer in your actual code looks a bit different. It uses a feature introduced in C99, called "designated initializers". With a normal initializer you have to list the values in order; in C99 you can prepend a "designator" that says where the value goes. The designator can be either an array index in brackets ( [ ] ) or a . followed by a member name. Designators can also be chained: [0].b = 42 means "initialize member b of element 0 of this array to 42".

That's what's going on here:

struct { int a[2], b; } arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

If we reorder the initializer by index, we get:

struct { int a[2], b; } arr[] = {[0].a = {1}, [0].b = 1, [1].a = {2}, [1].b = 2};

We can then merge adjacent designators:

struct { int a[2], b; } arr[] = {[0] = { .a = {1}, .b = 1 }, [1] = {.a = {2}, .b = 2} };

This makes it a bit easier to see that we're initializing two elements (so arr has size 2) and what the values actually are.

All of these forms are equivalent to:

struct { int a[2], b; } arr[] = { { {1}, 1 }, { {2}, 2 } };

You have declaring array of struct and [0].a , [0].b is a C99 syntax.

The [index] and .fieldname designators before an = to specify a nested subobject to initialize, the list is taken relative to the subobject corresponding to the closest surrounding brace pair.

refer this link .

the posted code has some incorrect initialization syntax.

I used the gcc compiler on ubuntu linux 16.04

the compiler output the following messages:

warning: missing initializer for field 'b' of 'struct <anonymous>' [-Wmissing-field-initializers]
arr[] = {[0].a = {1}, [1].a = {2}, [0].b = 1, [1].b = 2};

note: 'b' declared here
int a[2], b;

the above lines are repeated twice.

please correct the syntax and repost

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM